package analizadorSemantico;

import java.io.FileNotFoundException;
import java.io.IOException;

import analizadorLexico.LexicalException;
import analizadorLexico.Token;
import analizadorLexico.AnalizadorLexico;
import analizadorSintactico.SyntacticException;
import tablaSimbolos.*;

public class AnalizadorSemantico {

	// Definici�n de los nombres de Tokens.
	private static final String TK_IDENTIFIER = "TK_identifier",
			TK_NUMERO = "TK_numero", TK_IF = "TK_if", TK_ELSE = "TK_else",
			TK_CLASS = "TK_class", TK_EXTENDS = "TK_extends",
			TK_NEW = "TK_new", TK_RETURN = "TK_return", TK_SUPER = "TK_super",
			TK_THIS = "TK_this", TK_WHILE = "TK_while",
			TK_BOOLEAN = "TK_boolean", TK_CHAR = "TK_char", TK_INT = "TK_int",
			TK_FOR = "TK_for", TK_VOID = "TK_void",
			TK_CLASSDEF = "TK_classDef",TK_STRING = "TK_string",
			TK_TRUE = "TK_true", TK_FALSE = "TK_false", TK_NULL = "TK_null",
			TK_MOD = "TK_mod", TK_OR = "TK_or", TK_AND = "TK_and",
			TK_MAS = "TK_mas", TK_MENOS = "TK_menos", TK_POR = "TK_por",
			TK_DIV = "TK_div", TK_COMA = "TK_coma", TK_PUNTO = "TK_punto",
			TK_DIGUAL = "TK_digual", TK_IGUAL = "TK_igual",
			TK_MAYIG = "TK_mayig", TK_MENIG = "TK_menig", TK_DIST = "TK_dist",
			TK_MEN = "TK_men", TK_MAY = "TK_may", TK_NOT = "TK_not",
			TK_CAD = "TK_cadena",TK_PARENTESISABRE = "TK_parentesisAbre",
			TK_PARENTESISCIERRA = "TK_parentesisCierra",
			TK_LLAVEABRE = "TK_llaveAbre", TK_LLAVECIERRA = "TK_llaveCierra",
			TK_PUNTOYCOMA = "TK_puntoycoma", TK_CHARLITERAL = "TK_charLiteral";
	// -----------------------------------------------------------------------------------------

	Token lookAhead;
	AnalizadorLexico ALex;	
	Generador gen;
	TablaSimbolos TS;
	//String paramVarID="";

	public AnalizadorSemantico(String File) {
		try {
			ALex = new AnalizadorLexico(File);
			lookAhead = ALex.getToken();
			gen = new Generador("source");
		} catch (FileNotFoundException e) {
			System.out.println("Error: Archivo no encontrado");
			System.exit(2);
		} catch (LexicalException l) {
			System.out.println(l.getMessage());
			System.exit(2);
		} catch (IOException l) {

		}
	}
	public AnalizadorSemantico(String File,String dest) {
		try {
			ALex = new AnalizadorLexico(File);
			lookAhead = ALex.getToken();
			if(!dest.equals(""))
				gen = new Generador(dest);
			else
				gen = new Generador("source");
		} catch (FileNotFoundException e) {
			System.out.println("Error: Archivo no encontrado");
			System.exit(2);
		} catch (LexicalException l) {
			System.out.println(l.getMessage());
			System.exit(2);
		} catch (IOException l) {

		}
	}

	void Start() throws SyntacticException, SemanticException {
		TS = new TablaSimbolos();
		generacionInicial();
		generacionMetodosSystem();
		if (lookAhead.get_nombre().equals(TK_CLASSDEF)) {
			ClassDef();
			ClassDefRep();
			// ***CHEQUEO SEMANTICO***
			EntradaClase clase = TS.getClase("main");
			if (clase == null || !clase.estaDeclarada())
				throw new SemanticException("La clase Main no se encuentra",lookAhead.get_numLinea());
			if (!clase.getConstructor().colaParamVacia())
				throw new SemanticException(
						"el constructor de la clase Main es incorrecto (no debe poseer parametros)",lookAhead.get_numLinea());
			// ***FIN CHEQUEO SEMANTICO***
			if (lookAhead.get_nombre().equals(TK_CLASS)) {
				Class();
				// ***CHEQUEO SEMANTICO***
				String metSindefinir = TS.chequearMetodos();
				if (metSindefinir != null)
					throw new SemanticException("m�todo \'" + metSindefinir
							+ "\' en clase \'"
							+ TS.getClaseActual().getNombre()
							+ "\' declarado pero no definido",lookAhead.get_numLinea());
				// ***FIN CHEQUEO SEMANTICO***
				ClassRep();
				String claseSindefinir = TS.chequearDefiniciones();
				TS.offsetear();
				if (claseSindefinir != null)
					throw new SemanticException("Clase \'"+claseSindefinir+"\' declarada pero no definida",lookAhead.get_numLinea());
			} else
				throw new SyntacticException("\'class\' ",
						lookAhead.get_lexema(), lookAhead.get_numLinea());
		} else
			throw new SyntacticException("\'classDef\' ",
					lookAhead.get_lexema(), lookAhead.get_numLinea());
	}

	void ClassDefRep() throws SyntacticException, SemanticException {
		if (lookAhead.get_nombre().equals(TK_CLASSDEF)) {
			ClassDef();
			ClassDefRep();
		}
	}

	void ClassRep() throws SyntacticException, SemanticException {
		if (lookAhead.get_nombre().equals(TK_CLASS)) {
			Class();
			String metSindefinir = TS.chequearMetodos();
			if (metSindefinir != null)
				throw new SemanticException("m�todo \'" + metSindefinir
						+ "\' en clase \'"
						+ TS.getClaseActual().getNombre()
						+ "\' declarado pero no definido",lookAhead.get_numLinea());
			ClassRep();
		}
	}

	void ClassDef() throws SyntacticException, SemanticException {
		if (lookAhead.get_nombre().equals(TK_CLASSDEF)) {
			Match(TK_CLASSDEF);
			if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
				// ***CHEQUEO SEMANTICO***
				String nomClass=lookAhead.get_lexema();
				EntradaClase clase = TS.getClase(lookAhead.get_lexema());
				if (clase != null && clase.estaDeclarada())
					throw new SemanticException("Nombre de clase repetido",lookAhead.get_numLinea());
				//else if (clase != null && !clase.estaDeclarada())
					//clase.declarada(true);
				else {
					clase = TS.agregarClase(lookAhead.get_lexema());
					//clase.declarada(true);
				}
				TS.setClaseActual(clase);
				String superDefiniendo = "false";
				// ***FIN CHEQUEO SEMANTICO
				Match(TK_IDENTIFIER);
				Super(superDefiniendo);
				if (lookAhead.get_nombre().equals(TK_LLAVEABRE)) {
					Match(TK_LLAVEABRE);
					clase.declarada(true);
					Def();
					if (lookAhead.get_nombre().equals(TK_LLAVECIERRA)) {
						Match(TK_LLAVECIERRA);						
					} else
						throw new SyntacticException("\'}\' ",
								lookAhead.get_lexema(),
								lookAhead.get_numLinea());
					// ***CHEQUEO SEMANTICO***
					if (TS.getClaseActual().getConstructor() == null){
						if(TS.getClaseActual().getNombre().equals("main"))
							System.out.println("WARNING!: constructor por defecto del \'main\'. El programa no va a hacer nada.");
						TS.getClaseActual().setConstructor();
						 //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
						 //Generacion de codigo de contructor por defecto
								gen.genLn("ctr_"+nomClass+":", "", "", "");
								gen.genLn("","LOADFP","",";enlace dinamico");
								gen.genLn("","LOADSP","","");
								gen.genLn("","STOREFP","",";se setea el FP al inicio del metodo llamado");
								gen.genLn("", "STOREFP", "", "");
								gen.genLn("", "RET", "1","");	
						 //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
					}
					// ***FIN CHEQUEO SEMANTICO***
				} else
					throw new SyntacticException("\'{\' ",
							lookAhead.get_lexema(), lookAhead.get_numLinea());
			} else
				throw new SyntacticException("un identificador de classdef ",
						lookAhead.get_lexema(), lookAhead.get_numLinea());
		} else
			throw new SyntacticException("\'classDef\' ",
					lookAhead.get_lexema(), lookAhead.get_numLinea());		
	}

	void Def() throws SyntacticException, SemanticException {
		if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
			String IdAnteriorH_CMDef = lookAhead.get_lexema();
			Match(TK_IDENTIFIER);
			CMDef(IdAnteriorH_CMDef);
		} else if (compString(new String[] { TK_BOOLEAN, TK_CHAR, TK_INT,
				TK_STRING }, lookAhead.get_nombre())) {
			Atributos atr_PrimitiveType = PrimitiveType();
			String Mdef_tipoH = atr_PrimitiveType.getAtributo("tipo");
			MDef(Mdef_tipoH);
		} else if (lookAhead.get_nombre().equals(TK_VOID)) {
			String MDef_tipoH = lookAhead.get_lexema();
			Match(TK_VOID);
			MDef(MDef_tipoH);
		}

	}

	void CMDef(String IdAnteriorH) throws SyntacticException, SemanticException {		
		if (lookAhead.get_nombre().equals(TK_PARENTESISABRE)) {
			// ***CHEQUEO SEMANTICO***
			if (!IdAnteriorH.equals(TS.getClaseActual().getNombre()))
				throw new SemanticException("Nombre invalido de constructor",lookAhead.get_numLinea());
			if (TS.getClaseActual().getConstructor() != null)
				throw new SemanticException("ya hay un constructor",
						lookAhead.get_numLinea());
			
				TS.setMetodoActual(TS.agregarConstructor());
		
			// ***FIN CHEQUEO SEMANTICO***

			FormalArgs("false", "false");
			TS.getMetodoActual().fixOffsets();
			if (lookAhead.get_nombre().equals(TK_PUNTOYCOMA)) {
				Match(TK_PUNTOYCOMA);
			} else
				throw new SyntacticException("\';\' ", lookAhead.get_lexema(),
						lookAhead.get_numLinea());
			Def();
		} else if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
			String MDef_tipoH = IdAnteriorH;
			MDef(MDef_tipoH);
		} else
			throw new SyntacticException("\'(\' o un identificador ",
					lookAhead.get_lexema(), lookAhead.get_numLinea());

	}

	void MDef(String tipo) throws SyntacticException, SemanticException {		
		if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
			// ***CHEQUEO SEMANTICO***
			String redefiniendo = "false";
			if (TS.getClaseActual().getMetodo(lookAhead.get_lexema()) != null
					|| TS.getClaseActual().getNombre()
							.equals(lookAhead.get_lexema()))
				throw new SemanticException(
						"el nombre del metodo ya fue utilizado",
						lookAhead.get_numLinea());
			if (TS.getClase(tipo) == null && !esTipoPrimitivo(tipo))
				TS.agregarClase(tipo); // lo agrega, pero no lo declara
			EntradaMetodo met = TS.getMetodoHeredado(lookAhead.get_lexema());
			
			String label=gen.labelMetodo(TS.getClaseActual().getNombre(),lookAhead.get_lexema());
			TS.setMetodoActual(TS.agregarMetodo(lookAhead.get_lexema(), tipo));
			TS.getClaseActual().getMetodo(lookAhead.get_lexema()).setLabel(label);
			
			
			if (met != null) {
				if (!(met.getTipo().equals(tipo)))
					throw new SemanticException(
							"el tipo del metodo a redefinir no coincide",
							lookAhead.get_numLinea());
				redefiniendo = "true";
				TS.getMetodoActual().setOffset(met.getOffset());
			}			
			
			
			// ***FIN CHEQUEO SEMANTICO***
			Match(TK_IDENTIFIER);
			FormalArgs("false", redefiniendo);
			if(redefiniendo.equals("false"))//si no estor redefiniendo, estoy declarando nomas, asi que le arreglo los offset
				TS.getMetodoActual().fixOffsets();
			if (lookAhead.get_nombre().equals(TK_PUNTOYCOMA)) {
				Match(TK_PUNTOYCOMA);
			} else
				throw new SyntacticException("\';\' ", lookAhead.get_lexema(),
						lookAhead.get_numLinea());
			MDefAux();
		} else
			throw new SyntacticException("un identificador ",
					lookAhead.get_lexema(), lookAhead.get_numLinea());
	}

	void MDefAux() throws SyntacticException, SemanticException {
		if (compString(new String[] { TK_IDENTIFIER, TK_BOOLEAN, TK_CHAR,
				TK_INT, TK_STRING, TK_VOID }, lookAhead.get_nombre())) {
			Atributos atr_MethodType = MethodType();
			String MDef_TipoH = atr_MethodType.getAtributo("tipo");
			MDef(MDef_TipoH);
		}
	}

	void Class() throws SyntacticException, SemanticException {
		if (lookAhead.get_nombre().equals(TK_CLASS)) {
			Match(TK_CLASS);
			if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
				String nomclase=lookAhead.get_lexema();
				// ***CHEQUEO SEMANTICO***
				EntradaClase clase = TS.getClase(lookAhead.get_lexema());
				if (clase == null || !clase.estaDeclarada())
					throw new SemanticException("La clase "
							+ lookAhead.get_lexema() + " No esta declarada",lookAhead.get_numLinea());
				TS.setClaseActual(clase);
				String definiendo = "true";
				// ***FIN CHEQUEO SEMANTICO***
				Match(TK_IDENTIFIER);
				Super(definiendo);
				//@@@@@@@@@@@@@@@@@  GENERACION DE CODIGO @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
		         String label_vt=clase.obtenerLabelMetodos();
		         gen.genLn("", ".DATA", "", "");
	        	 gen.genLn(gen.labelVT(nomclase)+":", "", "", "");
		         if(label_vt.equals("")){//no tiene metodos
		        	 gen.genLn("", "NOP","", "; no hay metodos, hay que rellenar con algo...");
		         }		         		       		        	 
		         else
		        	 gen.genLn("", "DW", label_vt, "; vt clase "+nomclase);		        	 
		         gen.genLn("", ".CODE", "", "");
				
				//@@@@@@@@@@@@@@@@@  FIN GENERACION DE CODIGO @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
				if (lookAhead.get_nombre().equals(TK_LLAVEABRE)) {
					Match(TK_LLAVEABRE);
					EnClase();
					if (lookAhead.get_nombre().equals(TK_LLAVECIERRA)) {
						Match(TK_LLAVECIERRA);
	
				
						
						clase.definida(true);
					} else
						throw new SyntacticException("\'}\' ",
								lookAhead.get_lexema(),
								lookAhead.get_numLinea());
				} else
					throw new SyntacticException("\'{\' ",
							lookAhead.get_lexema(), lookAhead.get_numLinea());
			} else
				throw new SyntacticException("un identificador ",
						lookAhead.get_lexema(), lookAhead.get_numLinea());
		} else
			throw new SyntacticException("\'class\' ", lookAhead.get_lexema(),
					lookAhead.get_numLinea());
	}

	void EnClase() throws SyntacticException, SemanticException {
		if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
			String VCM_IdAnteriorH = lookAhead.get_lexema();
			Match(TK_IDENTIFIER);
			VCM(VCM_IdAnteriorH);
		} else if (compString(new String[] { TK_BOOLEAN, TK_CHAR, TK_INT,
				TK_STRING }, lookAhead.get_nombre())) {
			Atributos atr_PrimitiveType = PrimitiveType();
			if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
				String EsMethodVar_tipo = atr_PrimitiveType.getAtributo("tipo");
				String EsMethodVar_IdAnteriorH = lookAhead.get_lexema();
				Match(TK_IDENTIFIER);
				if (compString(new String[] { TK_COMA, TK_PARENTESISABRE,
						TK_PUNTOYCOMA }, lookAhead.get_nombre())) {
					EsMethodVar(EsMethodVar_tipo, EsMethodVar_IdAnteriorH);
				}
			}

		} else if (lookAhead.get_nombre().equals(TK_VOID)) {
			String EsMetodo_tipo = lookAhead.get_lexema();
			Match(TK_VOID);
			if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
				String EsMetodo_IdAnteriorH = lookAhead.get_lexema();
				Match(TK_IDENTIFIER);
				EsMetodo(EsMetodo_tipo, EsMetodo_IdAnteriorH);
			} else
				throw new SyntacticException("un identificador ",
						lookAhead.get_lexema(), lookAhead.get_numLinea());
		}
	}

	void VCM(String IdAnteriorH) throws SyntacticException, SemanticException {
		if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
			String EsMethodVar_Tipo = IdAnteriorH;
			String EsMethodVar_IdAnteriorH = lookAhead.get_lexema();
			Match(TK_IDENTIFIER);
			if (compString(new String[] { TK_COMA, TK_PARENTESISABRE,
					TK_PUNTOYCOMA, TK_LLAVECIERRA }, lookAhead.get_nombre())) {
				EsMethodVar(EsMethodVar_Tipo, EsMethodVar_IdAnteriorH);
			} else
				throw new SyntacticException("\',\' o \'(\' ",
						lookAhead.get_lexema(), lookAhead.get_numLinea());
		} else if (lookAhead.get_nombre().equals(TK_PARENTESISABRE)) {
			// ****CHEQUEO SEMANTICO**
			if (!IdAnteriorH.equals(TS.getClaseActual().getNombre()))
				throw new SemanticException(
						"El nombre del constructor no es valido",
						lookAhead.get_numLinea());
			String esContructor_IdAnteriorH = IdAnteriorH;
			// ****FIN CHEQUEO SEMANTICO**
			EsConstructor(esContructor_IdAnteriorH);
		} else
			throw new SyntacticException("\'(\' ", lookAhead.get_lexema(),
					lookAhead.get_numLinea());
	}

	// esta distinto a la gramatica, por facilidad de escritura en el c�digo
	void EsMethodVar(String tipo, String IdAnteriorH)
			throws SyntacticException, SemanticException {
		if (lookAhead.get_nombre().equals(TK_PARENTESISABRE)) {
			String EsMetodo_IdAnteriorH = IdAnteriorH;
			EsMetodo(tipo, EsMetodo_IdAnteriorH);
		} else {
			EntradaClase clase = TS.getClaseActual();
			if (clase.getMetodo(IdAnteriorH) != null
					|| clase.getVariable(IdAnteriorH) != null
					|| TS.getMetodoHeredado(IdAnteriorH) != null)
				throw new SemanticException(
						"Nombre de la variable ya utilizado",
						lookAhead.get_numLinea());
			if (clase.getNombre().equals(IdAnteriorH))
				throw new SemanticException("El nombre de la variable es el mismo que el de la clase",lookAhead.get_numLinea());
			if (TS.getClase(tipo) == null && !esTipoPrimitivo(tipo))
				throw new SemanticException("El tipo no es primitivo ni se corresponde con una clase declarada",lookAhead.get_numLinea());
			clase.agregarVariable(tipo, IdAnteriorH);
			VarDeclaratorListRep(tipo);
			if (lookAhead.get_nombre().equals(TK_PUNTOYCOMA)) {
				Match(TK_PUNTOYCOMA);
				EnClase();
			} else
				throw new SyntacticException("\';\' ", lookAhead.get_lexema(),
						lookAhead.get_numLinea());
		}
	}

	void EsMetodo(String tipo, String IdAnteriorH) throws SyntacticException,
			SemanticException {
		if (lookAhead.get_nombre().equals(TK_PARENTESISABRE)) {
			// ***CHEQUEO SEMANTICO***
			EntradaMetodo met = TS.getClaseActual().getMetodo(IdAnteriorH);
			if (met == null)
				throw new SemanticException("metodo no declarado",
						lookAhead.get_numLinea());
			if (!met.getTipo().equals(tipo))
				throw new SemanticException(
						"el tipo del metodo declarado no coincide con su definici�n",
						lookAhead.get_numLinea());
			TS.setMetodoActual(IdAnteriorH);
			String FormalArgs_definiendo = "true";
			// ***FIN CHEQUEO SEMANTICO***
			FormalArgs(FormalArgs_definiendo, "false"); // si defino, no
														// redefino. Se
														// "redefine" en la
														// declaracion
														
			//@@@@@@@@@@@@@	
			gen.genLn(TS.getMetodoActual().getLabel()+":", "", "", "");
			gen.genLn("","LOADFP","",";enlace dinamico");
			gen.genLn("","LOADSP","","");
			gen.genLn("","STOREFP","",";se setea el FP al inicio del metodo llamado");
			//@@@@@@@@@@@@@	
			Atributos Block_atr = Block();
			gen.genLn("","STOREFP","", ";setea el FP en la ubicacion correspondiente al llamador");
			gen.genLn("","RET",""+(TS.getMetodoActual().getCantParams()+1), ";Saca los parametros y el this (no es void)");
			TS.getMetodoActual().definir(true);
			// ***CHEQUEO SEMANTICO***
			if (Block_atr.getAtributo("hayReturn").equals("false")
					&& !tipo.equals("void"))
				throw new SemanticException(
						"Error, el metodo requiere de return",
						lookAhead.get_numLinea());
			// ***FIN CHEQUEO SEMANTICO***
			Method();
		} else
			throw new SyntacticException("\'(\' ", lookAhead.get_lexema(),
					lookAhead.get_numLinea());
	}

	void EsConstructor(String IdAnteriorH) throws SyntacticException,SemanticException {
		if (lookAhead.get_nombre().equals(TK_PARENTESISABRE)) {
			// ***CHEQUEO SEMANTICO***
			EntradaClase clase = TS.getClaseActual();
			if (!clase.getConstructor().estaDeclarado())
				throw new SemanticException("Constructor no declarado",lookAhead.get_numLinea());
			if (clase.getConstructor().estaDefinido())
				throw new SemanticException("Constructor ya definido",lookAhead.get_numLinea());			
			if (!IdAnteriorH.equals(clase.getNombre()))
				throw new SemanticException("Constructor con nombre invalido",
						lookAhead.get_numLinea());
			TS.setMetodoActual(IdAnteriorH);
			// ***FIN CHEQUEO SEMANTICO***
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			gen.genLn(gen.labelConstructor(IdAnteriorH)+":", "", "", "");
			gen.genLn("","LOADFP","",";enlace dinamico");
			gen.genLn("","LOADSP","","");
			gen.genLn("","STOREFP","",";se setea el FP al inicio del metodo llamado");
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			FormalArgs("true", "false");
			Atributos Block_atr = Block();
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			gen.genLn("", "STOREFP", "", "");
			gen.genLn("","RET",""+(TS.getMetodoActual().getCantParams()+1), ";Saca los parametros y el this");
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			// ***CHEQUEO SEMANTICO***
			if (Block_atr.getAtributo("hayReturn").equals("true"))
				throw new SemanticException(
						"Constructor con return en el bloque",
						lookAhead.get_numLinea());
			// ***FIN CHEQUEO SEMANTICO***

			CtorMethod();
		} else
			throw new SyntacticException("\'(\' ", lookAhead.get_lexema(),
					lookAhead.get_numLinea());
	}

	void CtorMethod() throws SyntacticException, SemanticException {
		if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
			String esCons_IdAnteriorH = lookAhead.get_lexema();
			Match(TK_IDENTIFIER);
			EsConstructorMetodo(esCons_IdAnteriorH);
		} else if (lookAhead.get_nombre().equals(TK_VOID)) {
			String esMet_tipo = lookAhead.get_lexema();
			Match(TK_VOID);
			if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
				String esMet_IdAnteriorH = lookAhead.get_lexema();
				Match(TK_IDENTIFIER);
				EsMetodo(esMet_tipo, esMet_IdAnteriorH);
			} else
				throw new SyntacticException("un identificador ",
						lookAhead.get_lexema(), lookAhead.get_numLinea());
		} else if (compString(new String[] { TK_BOOLEAN, TK_CHAR, TK_INT,
				TK_STRING }, lookAhead.get_nombre())) {
			Atributos atr_PrimitiveType = PrimitiveType();
			if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
				String IdAnteriorH = lookAhead.get_lexema();
				Match(TK_IDENTIFIER);
				EsMetodo(atr_PrimitiveType.getAtributo("tipo"), IdAnteriorH);
			} else
				throw new SyntacticException("un identificador ",
						lookAhead.get_lexema(), lookAhead.get_numLinea());
		}
	}

	void EsConstructorMetodo(String IdAnteriorH) throws SyntacticException,
			SemanticException {
		if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
			if (TS.getClase(IdAnteriorH) == null)
				throw new SemanticException("No existe el tipo",
						lookAhead.get_numLinea());
			String esMet_IdAnteriorH = lookAhead.get_lexema();
			String esMet_tipo = IdAnteriorH;
			Match(TK_IDENTIFIER);
			EsMetodo(esMet_tipo, esMet_IdAnteriorH);
		} else if (lookAhead.get_nombre().equals(TK_PARENTESISABRE)) {
			String EsCon_IdAnteriorH = IdAnteriorH;
			EsConstructor(EsCon_IdAnteriorH);
		}
	}

	void VarDeclaratorList(String tipo) throws SyntacticException,
			SemanticException {
		if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
			EntradaClase clase = TS.getClaseActual();
			if (clase.getMetodo(lookAhead.get_lexema()) != null
					|| TS.getMetodoHeredado(lookAhead.get_lexema()) != null
					|| clase.getVariable(lookAhead.get_lexema()) != null)

				throw new SemanticException("Nombre ya utilizado",
						lookAhead.get_numLinea());
			if (clase.getNombre().equals(lookAhead.get_lexema()))
				throw new SemanticException(
						"La variable tiene el mismo nombre que la clase",
						lookAhead.get_numLinea());
			clase.agregarVariable(tipo, lookAhead.get_lexema());
			Match(TK_IDENTIFIER);
			VarDeclaratorListRep(tipo);
		} else
			throw new SyntacticException("un identificador",
					lookAhead.get_lexema(), lookAhead.get_numLinea());
	}

	void VarDeclaratorListRep(String tipo) throws SyntacticException,
			SemanticException {
		if (lookAhead.get_nombre().equals(TK_COMA)) {
			Match(TK_COMA);
			VarDeclaratorList(tipo);
		}
	}

	void Super(String definiendo) throws SyntacticException, SemanticException {
		if (lookAhead.get_nombre().equals(TK_EXTENDS)) {
			Match(TK_EXTENDS);
			if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
				// ***CHEQUEO SEMANTICO***
				if (definiendo.equals("false")) {
					if (TS.getClase(lookAhead.get_lexema()) == null)
						throw new SemanticException("Clase no declarada",
								lookAhead.get_numLinea());
					TS.getClaseActual().setPadre(TS.getClase(lookAhead.get_lexema()));
					if (TS.esHerenciaCircular(TS.getClaseActual()))
						throw new SemanticException("Herencia circular",
								lookAhead.get_numLinea());					
				} else { // la estoy definiendo, no declarando
					if (TS.getClaseActual().getPadre() == null)
						throw new SemanticException(
								"La declaraci�n no especifica un padre",
								lookAhead.get_numLinea());
					if (!TS.getClaseActual().getPadre().getNombre()
							.equals(lookAhead.get_lexema()))
						throw new SemanticException("Clase padre inv�lida",
								lookAhead.get_numLinea());
				}
				// ***FIN CHEQUEO SEMANTICO***
				Match(TK_IDENTIFIER);
			} else {
				throw new SyntacticException("un identificador de clase base ",
						lookAhead.get_lexema(), lookAhead.get_numLinea());

			}
		} else {
			if(definiendo.equals("true") && !TS.getClaseActual().getPadre().getNombre().equals("Object"))
				throw new SemanticException("falta especificar la herencia en la definicion de la clase "+TS.getClaseActual().getNombre(), lookAhead.get_numLinea());
			TS.getClaseActual().setPadre(TS.getClase("Object"));
		}
	}


	void Method() throws SyntacticException, SemanticException {
		if (compString(new String[] { TK_VOID, TK_IDENTIFIER, TK_BOOLEAN,
				TK_CHAR, TK_INT, TK_STRING }, lookAhead.get_nombre())) {
			Atributos atr_MthodType = MethodType();
			if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
				String tipo = atr_MthodType.getAtributo("tipo");
				String EsMetodo_IdAnteriorH = lookAhead.get_lexema();
				Match(TK_IDENTIFIER);
				EsMetodo(tipo, EsMetodo_IdAnteriorH);
			} else {
				throw new SyntacticException("un identificador de Metodo",
						lookAhead.get_lexema(), lookAhead.get_numLinea());
			}

		} else {

		}
	}



	void FormalArgs(String definiendo, String redefiniendo)
			throws SyntacticException, SemanticException {
		if (lookAhead.get_nombre().equals(TK_PARENTESISABRE)) {
			Match(TK_PARENTESISABRE);
		} else {
			throw new SyntacticException("\'(\'  ", lookAhead.get_lexema(),
					lookAhead.get_numLinea());

		}
		FormalArgsListM(definiendo,redefiniendo);

		if (lookAhead.get_nombre().equals(TK_PARENTESISCIERRA)) {
			Match(TK_PARENTESISCIERRA);
		} else {
			throw new SyntacticException(" parantesis ')'  ",
					lookAhead.get_lexema(), lookAhead.get_numLinea());
		}
		if (definiendo.equals("true")){
			if (!TS.getMetodoActual().colaParamVacia())
				throw new SemanticException("faltan parametros en el metodo",
						lookAhead.get_numLinea());
		}
		else
			if(redefiniendo.equals("true"))
				if (!TS.getMetodoHeredado(TS.getMetodoActual().getNombre()).colaParamVacia())
					throw new SemanticException("faltan parametros en el metodo",
							lookAhead.get_numLinea());

	}

	void FormalArgsListM(String definiendo, String redefiniendo)
			throws SyntacticException, SemanticException {
		if (compString(new String[] { TK_VOID, TK_IDENTIFIER, TK_BOOLEAN,
				TK_CHAR, TK_INT, TK_STRING }, lookAhead.get_nombre())){
			FormalArgsList(definiendo, redefiniendo);			
			
		}
		else {
			// lambda
		}
	}

	void FormalArgsList(String definiendo, String redefiniendo)
			throws SyntacticException, SemanticException {
		Atributos atr_FormalArg = FormalArg();
		String tipoParam = atr_FormalArg.getAtributo("tipo");
		String nombreParam = atr_FormalArg.getAtributo("lexema");
		if (redefiniendo.equals("true")) {
			EntradaMetodo met = TS.getMetodoHeredado(TS.getMetodoActual()
					.getNombre());
			if (!TS.chequearParaReDef(met, nombreParam, tipoParam))
				throw new SemanticException(
						"los parametros no coinciden con los del metodo a redefinir",
						lookAhead.get_numLinea());
			TS.agregarParam(nombreParam, tipoParam);
		} else if (!definiendo.equals("true")) {
			// si el tipo es != nulo, es porq ya existe un parametro con ese
			// nombre
			if (TS.getMetodoActual().getParamTipo(
					atr_FormalArg.getAtributo("lexema")) != null)
				throw new SemanticException(
						"Ya existe un parametro con ese nombre",
						lookAhead.get_numLinea());
			if (!esTipoPrimitivo(tipoParam))
				if (TS.getClase(tipoParam) == null)
					TS.agregarClase(tipoParam);
			TS.agregarParam(nombreParam, tipoParam);
		} else { // no redefino ni declaro, DEFINO
			if (!TS.chequearParamDef(nombreParam, tipoParam))
				throw new SemanticException(
						"El parametro no se corresponde con su declaracion",
						lookAhead.get_numLinea());
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
		
			if (TS.getMetodoActual().getParam(nombreParam)!=null){
				
				TS.getMetodoActual().getParam(nombreParam).setEsParam(true);
		
			}
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
		}

		FAL(definiendo, redefiniendo);
	}

	void FAL(String definiendo, String redefiniendo) throws SyntacticException,
			SemanticException {
		if (lookAhead.get_nombre().equals(TK_COMA)) {
			Match(TK_COMA);
			FormalArgsList(definiendo, redefiniendo);
		} else {
			// Lambda
		}

	}

	Atributos FormalArg() throws SyntacticException {
		Atributos atribs = new Atributos();
		if (compString(new String[] { TK_IDENTIFIER, TK_BOOLEAN, TK_CHAR,
				TK_INT, TK_STRING }, lookAhead.get_nombre())) {
			Atributos atr_Type = Type();
			atribs.addAtributo("tipo", atr_Type.getAtributo("tipo"));
		} else {
			throw new SyntacticException(" un tipo ", lookAhead.get_lexema(),
					lookAhead.get_numLinea());

		}
		if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
			atribs.addAtributo("lexema", lookAhead.get_lexema());
			Match(TK_IDENTIFIER);
		} else {
			throw new SyntacticException(" identificador ",
					lookAhead.get_lexema(), lookAhead.get_numLinea());

		}
		return atribs;
	}

	Atributos MethodType() throws SyntacticException {
		Atributos atr = new Atributos();
		String tipo = null;
		if (compString(new String[] { TK_IDENTIFIER, TK_BOOLEAN, TK_CHAR,
				TK_INT, TK_STRING }, lookAhead.get_nombre())) {
			Atributos atr_Type = Type();
			tipo = atr_Type.getAtributo("tipo");
		} else if (lookAhead.get_nombre().equals(TK_VOID)) {
			tipo = lookAhead.get_lexema();
			Match(TK_VOID);
		} else {
			throw new SyntacticException("Se esperaba un tipo ",
					lookAhead.get_lexema(), lookAhead.get_numLinea());

		}
		atr.addAtributo("tipo", tipo);
		return atr;
	}

	Atributos Type() throws SyntacticException {
		Atributos atr = new Atributos();
		if (compString(new String[] { TK_BOOLEAN, TK_CHAR, TK_INT, TK_STRING },
				lookAhead.get_nombre())) {
			Atributos atr_PrimitiveType = PrimitiveType();
			atr.addAtributo("tipo", atr_PrimitiveType.getAtributo("tipo"));
		} else if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
			EntradaClase clase = TS.getClase(lookAhead.get_lexema());
			if (clase != null)
				atr.addAtributo("tipo", clase.getNombre());
			else{
				atr.addAtributo("tipo", lookAhead.get_lexema());
				TS.agregarClase(lookAhead.get_lexema());
			}
			Match(TK_IDENTIFIER);
		} else {
			throw new SyntacticException(" un tipo  ", lookAhead.get_lexema(),
					lookAhead.get_numLinea());

		}
		return atr;
	}

	Atributos PrimitiveType() throws SyntacticException {
		Atributos atr = new Atributos();
		String tipoLex;
		if (lookAhead.get_nombre().equals(TK_BOOLEAN)) {
			tipoLex = lookAhead.get_lexema();
			Match(TK_BOOLEAN);
		} else if (lookAhead.get_nombre().equals(TK_CHAR)) {
			tipoLex = lookAhead.get_lexema();
			Match(TK_CHAR);
		} else if (lookAhead.get_nombre().equals(TK_INT)) {
			tipoLex = lookAhead.get_lexema();
			Match(TK_INT);
		} else if (lookAhead.get_nombre().equals(TK_STRING)) {
			tipoLex = lookAhead.get_lexema();
			Match(TK_STRING);
		} else {
			throw new SyntacticException(" No es un tipo primitivo ",
					lookAhead.get_lexema(), lookAhead.get_numLinea());
		}
		atr.addAtributo("tipo", tipoLex);
		return atr;

	}

	Atributos Block() throws SyntacticException, SemanticException {
		Atributos atr = new Atributos();
		if (lookAhead.get_nombre().equals(TK_LLAVEABRE)) {
			Match(TK_LLAVEABRE);
			Atributos atr_st = StatementRep();
			atr.addAtributo("hayReturn", atr_st.getAtributo("hayReturn"));
			if (lookAhead.get_nombre().equals(TK_LLAVECIERRA)) {
				Match(TK_LLAVECIERRA);
			} else {
				throw new SyntacticException(" '}' o declaracion de metodo ",
						lookAhead.get_lexema(), lookAhead.get_numLinea());

			}
		} else {
			throw new SyntacticException(" '{'  ", lookAhead.get_lexema(),
					lookAhead.get_numLinea());

		}
		return atr;
	}

	Atributos StatementRep() throws SyntacticException, SemanticException {
		Atributos atr = new Atributos();
		String resul = "false";
		if (compString(new String[] { TK_PUNTOYCOMA, TK_IF, TK_RETURN,
				TK_LLAVEABRE, TK_FOR, TK_WHILE, TK_NOT, TK_MAS, TK_MENOS,
				TK_NULL, TK_TRUE, TK_FALSE, TK_NUMERO, TK_CHARLITERAL, TK_CAD,
				TK_PARENTESISABRE, TK_NEW, TK_SUPER, TK_THIS, TK_IDENTIFIER },
				lookAhead.get_nombre())) {
			Atributos atr_St = Statement();
			Atributos atr_StR = StatementRep();

			if (atr_St.getAtributo("hayReturn").equals("true")
					|| atr_StR.getAtributo("hayReturn").equals("true"))
				resul = "true";
		} else {
			// lambda
			// hayReturn queda como falso
		}
		atr.addAtributo("hayReturn", resul);
		return atr;
	}

	Atributos Statement() throws SyntacticException, SemanticException {
		Atributos atr = new Atributos();
		String hayRet = "false";
		if (lookAhead.get_nombre().equals(TK_PUNTOYCOMA)) {// hayReturn = false
			Match(TK_PUNTOYCOMA);			

		} else if (lookAhead.get_nombre().equals(TK_IF)) {
			Match(TK_IF);
			if (lookAhead.get_nombre().equals(TK_PARENTESISABRE)) {
				Match(TK_PARENTESISABRE);
			} else {
				throw new SyntacticException(" parantesis '('  ",
						lookAhead.get_lexema(), lookAhead.get_numLinea());
			}
			Atributos atr_Exp = Expression();
	
			if (!atr_Exp.getAtributo("tipo").equals("boolean"))
				throw new SemanticException(
						"Se esperaba una expresion de tipo booleano",
						lookAhead.get_numLinea());
			if (lookAhead.get_nombre().equals(TK_PARENTESISCIERRA)) {
				Match(TK_PARENTESISCIERRA);
			} else {
				throw new SyntacticException(" parantesis '('  ",
						lookAhead.get_lexema(), lookAhead.get_numLinea());
			}
			// ***SEMANTICO***
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			String l1=gen.labelIfElse();
			String l2=gen.labelIfEnd(l1);
			gen.genLn("", "BF", l1, "; codigo then");
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			Atributos atr_St = Statement();
			gen.genLn("", "JUMP", l2, "");
			Atributos atr_STIF = STIF(l1,l2);
			
			String hayRetSt = atr_St.getAtributo("hayReturn");
			String hayRetSTIF = atr_STIF.getAtributo("hayReturn");

			if (hayRetSt.equals("true") && hayRetSTIF.equals("true"))
				hayRet = "true";
			// ***FIN SEMANTICO***
		} else if (lookAhead.get_nombre().equals(TK_RETURN)) {
			Match(TK_RETURN);
			Atributos atr_expM = ExpressionM();
			//@@@ GENERACION DE CODIGO @@@
			if(!atr_expM.getAtributo("esNull").equals("nada"))
				gen.genLn("","STORE",""+(TS.getMetodoActual().getOffParam()+3),";hacemos el store en el valor de retorno");
			//@@@ FIN GENERACION DE CODIGO @@@
			// ***CHEQUEO SEMANTICO***
			String tipoExpM = atr_expM.getAtributo("tipo");
			String tipoEspera = TS.getMetodoActual().getTipo();
			String esNull = atr_expM.getAtributo("esNull");
			if (!TS.esConformante(tipoEspera, tipoExpM,esNull)
					|| (tipoEspera.equals("void") && atr_expM.getAtributo(
							"esNull").equals("true")))
			if(!tipoEspera.equals("void"))	
				throw new SemanticException("se esperaba tipo \'" + tipoEspera+ "\' y se encontro \'" + tipoExpM + "\'",lookAhead.get_numLinea());
			else
				throw new SemanticException("El metodo es de tipo void, no debe devolver un resultado",lookAhead.get_numLinea());

			// ***FIN CHEQUEO SEMANTICO***
			hayRet = "true";
			if (lookAhead.get_nombre().equals(TK_PUNTOYCOMA)) {
				Match(TK_PUNTOYCOMA);
			} else {
				throw new SyntacticException(" ';' ", lookAhead.get_lexema(),
						lookAhead.get_numLinea());

			}
		} else if (lookAhead.get_nombre().equals(TK_LLAVEABRE)) {
			Atributos atr_bl = Block();
			hayRet = atr_bl.getAtributo("hayReturn");
		} else if (lookAhead.get_nombre().equals(TK_FOR)) {
			Match(TK_FOR);
			if (lookAhead.get_nombre().equals(TK_PARENTESISABRE)) {
				Match(TK_PARENTESISABRE);
			} else {
				throw new SyntacticException(" parantesis '('  ",
						lookAhead.get_lexema(), lookAhead.get_numLinea());
			}
			// exp 1
			Expression();
		    gen.genLn("", "POP", "","; POP FOR");
			if (lookAhead.get_nombre().equals(TK_PUNTOYCOMA)) {
				Match(TK_PUNTOYCOMA);
			} else {
				throw new SyntacticException(
						"Error en linea "
								+ lookAhead.get_numLinea()
								+ ": Ingrese ';Expresion;Expresion' Para completar la declaraci�n del For");
			}
			// exp 2
			String forini=gen.labelFor();
			String forFin=gen.labelForFin(forini);
			String bloqueFor=forini+"_bloque";
			String terceraExpresion=forini+"_expTERCERA";
			gen.genLn(forini+":", "", "", "; inicio for");
			Atributos atr_Exp2 = Expression();
			gen.genLn("", "BF", forFin, "; fin for");
			
			if (!atr_Exp2.getAtributo("tipo").equals("boolean"))
				throw new SemanticException(
						"se esperaba un tipo boolean en la segunda expresion del for",
						lookAhead.get_numLinea());

			if (lookAhead.get_nombre().equals(TK_PUNTOYCOMA)) {
				Match(TK_PUNTOYCOMA);
			} else {
				throw new SyntacticException(
						"Error en linea "
								+ lookAhead.get_numLinea()
								+ ": Ingrese ';Expresion' Para completar la declaraci�n del For");
			}
			// exp 3
			gen.genLn("", "JUMP", bloqueFor, "; salta bloque");
			gen.genLn(terceraExpresion+":", "", "", "; inicio ultima expresion");
			Expression();
			gen.genLn("", "POP", "","; POP FOR");
			gen.genLn("", "JUMP", forini, "; salta inicio for");
			if (lookAhead.get_nombre().equals(TK_PARENTESISCIERRA)) {
				Match(TK_PARENTESISCIERRA);
			} else {
				throw new SyntacticException(" parantesis '('  ",
						lookAhead.get_lexema(), lookAhead.get_numLinea());
			}
			gen.genLn(bloqueFor+":", "", "", "; bloque for");
			Statement();
			gen.genLn("", "JUMP", terceraExpresion, "; evaluo ultima expresion");
			gen.genLn(forFin+":", "", "", "; fin for");
		} else if (compString(new String[] { TK_NOT, TK_MAS, TK_MENOS, TK_NULL,
				TK_TRUE, TK_FALSE, TK_NUMERO, TK_CHARLITERAL, TK_CAD,
				TK_PARENTESISABRE, TK_NEW, TK_SUPER, TK_THIS, TK_IDENTIFIER },
				lookAhead.get_nombre())) {
			Expression();
			if (lookAhead.get_nombre().equals(TK_PUNTOYCOMA)) {
				Match(TK_PUNTOYCOMA);
				gen.genLn("", "POP","","; sacamos el valor excesivo de la expresion");
			} else {
				throw new SyntacticException("un ; ", lookAhead.get_lexema(),
						lookAhead.get_numLinea());
			}
		} else if (lookAhead.get_nombre().equals(TK_WHILE)) {
			Match(TK_WHILE);
			if (lookAhead.get_nombre().equals(TK_PARENTESISABRE)) {
				Match(TK_PARENTESISABRE);
			} else {
				throw new SyntacticException(" parantesis '('  ",
						lookAhead.get_lexema(), lookAhead.get_numLinea());
			}
			String whileLab=gen.labelWhile();
			String whileFin =gen.labelWhileFin(whileLab);
			gen.genLn(whileLab+":", "", "", "");
			Atributos atr_expWhile = Expression();
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			gen.genLn("", "BF", whileFin, "; fin del while");
			
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			if (!atr_expWhile.getAtributo("tipo").equals("boolean"))
				throw new SemanticException(
						"se esperaba un tipo boolean en la condicion del while",
						lookAhead.get_numLinea());
			if (lookAhead.get_nombre().equals(TK_PARENTESISCIERRA)) {
				Match(TK_PARENTESISCIERRA);
			} else {
				throw new SyntacticException(" parantesis '('  ",
						lookAhead.get_lexema(), lookAhead.get_numLinea());
			}
			Statement();
			gen.genLn("", "JUMP", whileLab, "; inicio while");
			gen.genLn(whileFin+ ":", "", "", "");

		} else {

			throw new SyntacticException("una sentencia valida",
					lookAhead.get_lexema(), lookAhead.get_numLinea());

		}
		atr.addAtributo("hayReturn", hayRet);
		return atr;

	}

	Atributos ExpressionM() throws SyntacticException, SemanticException {
		Atributos atribExpressionM = new Atributos();
		if (compString(new String[] { TK_NOT, TK_MAS, TK_MENOS, TK_NULL,
				TK_TRUE, TK_FALSE, TK_NUMERO, TK_CHARLITERAL, TK_CAD,
				TK_PARENTESISABRE, TK_NEW, TK_SUPER, TK_THIS, TK_IDENTIFIER },
				lookAhead.get_nombre())) {
			Atributos atribExpresion = Expression();
			atribExpressionM.addAtributo("tipo",atribExpresion.getAtributo("tipo"));
			atribExpressionM.addAtributo("esNull",atribExpresion.getAtributo("esNull"));

		} else {
			// lambda
			atribExpressionM.addAtributo("tipo","void");
			atribExpressionM.addAtributo("esNull","nada");
		}
		return atribExpressionM;

	}

	Atributos STIF(String lelse, String lfin) throws SyntacticException, SemanticException {
		Atributos atribSTIF = new Atributos();
		gen.genLn(lelse+":", "", "", "; else");
		if (lookAhead.get_nombre().equals(TK_ELSE)) {
			Match(TK_ELSE);
		
			Atributos atribStatement = Statement();
			atribSTIF.addAtributo("hayReturn",
					atribStatement.getAtributo("hayReturn"));
		} else {
			gen.genLn("","NOP","","; Para que no explote con 2 labels seguidas");
			// lambda
			atribSTIF.addAtributo("hayReturn","false");
		}
		gen.genLn(lfin+":","","","; fin del if");
		return atribSTIF;

	}

	Atributos Expression() throws SyntacticException, SemanticException {
		// ***CHEQUEO SEMANTICO***
		Atributos atribExpresion = new Atributos();
		Atributos atribExpresionIgual = ExpresionIgual();
		atribExpresion.addAtributo("paramVarID",atribExpresionIgual.getAtributo("paramVarID"));
		String esNull = "false";

		Atributos atribExpAsig = ExpAsig(atribExpresion.getAtributo("paramVarID"),atribExpresionIgual.getAtributo("tipo"),atribExpresionIgual.getAtributo("esAsignable"));
		atribExpresion.addAtributo("tipo", atribExpAsig.getAtributo("tipo"));
		
		if(atribExpAsig.getAtributo("esNull").equals("true") && atribExpresionIgual.getAtributo("esNull").equals("true"))
			esNull = "true";
		// fin
		atribExpresion.addAtributo("esNull", esNull);
		return atribExpresion;
	}

	Atributos ExpAsig(String paramVarID, String TH, String esAsignable) throws SemanticException,SyntacticException {
		Atributos atribExpAsig = new Atributos();
		
		if (lookAhead.get_nombre().equals(TK_IGUAL)) {
			Match(TK_IGUAL);
			gen.genLn("", "POP", "", "");
			// ***CHEQUEO SEMANTICO***

			if (!esAsignable.equals("true"))
				throw new SemanticException("no es asignable",lookAhead.get_numLinea());
			Atributos atribExpression = Expression();
			gen.genLn("", "DUP","","; duplico por si es asignacion multiple");
			if (TS.esConformante(TH, atribExpression.getAtributo("tipo"),atribExpression.getAtributo("esNull"))) {
				atribExpAsig.addAtributo("tipo",atribExpression.getAtributo("tipo"));
			} else {
				throw new SemanticException("incompatibilidad de tipos",lookAhead.get_numLinea());
			}
			atribExpAsig.addAtributo("esNull", "false");
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			EntradaVariable varOpar = TS.getMetodoActual().getParam(paramVarID); 
			
			if (varOpar != null){// es un parametro			
				gen.genLn("", "STORE",""+(3+varOpar.getOffset()),";guardo en el parametro "+varOpar.getNombre() );
			}
			else{
				varOpar = TS.getClaseActual().getVariable(paramVarID);
				if(varOpar != null){
					// es una variable
					gen.genLn("", "LOAD",3+"", "; cargamos la referencia al this");
					gen.genLn("","SWAP","","; swapeamos entre el this y el valor a almacenar");
					gen.genLnConOffset("", "STOREREF",""+gen.labelOffset(TS.getClaseActual().getNombre(), paramVarID),";guardo la variable "+varOpar.getNombre() );
				}//si es nulo es porq no era un id.
			}
				
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			
			return atribExpAsig;			

		} else {			
			atribExpAsig.addAtributo("esNull", "true");
			atribExpAsig.addAtributo("tipo", TH);
			return atribExpAsig;
		}
	}

	Atributos ExpresionIgual() throws SyntacticException, SemanticException {
		String esAsignable = "false";
		String esNull = "false";
		Atributos atribExpresionIgual = new Atributos();
		Atributos atribExpresionOr = ExpresionOr();
		Atributos atribExpIg = ExpIg(atribExpresionOr.getAtributo("tipo"));
		atribExpresionIgual.addAtributo("paramVarID",atribExpresionOr.getAtributo("paramVarID"));

		String esAsignExpOr = atribExpresionOr.getAtributo("esAsignable");
		String esAsignExpIg = atribExpIg.getAtributo("esAsignable");
		if(esAsignExpIg.equals("true") && esAsignExpOr.equals("true"))
			esAsignable = "true";
		
		String esNullExpOr = atribExpresionOr.getAtributo("esNull");
		String esNullExpIg = atribExpIg.getAtributo("esNull");
		if(esNullExpIg.equals("true") && esNullExpOr.equals("true"))
			esNull = "true";
		
		atribExpresionIgual.addAtributo("tipo", atribExpIg.getAtributo("tipo"));
		atribExpresionIgual.addAtributo("esAsignable", esAsignable);
		atribExpresionIgual.addAtributo("esNull", esNull);
		return atribExpresionIgual;
	}

	Atributos ExpresionOr() throws SyntacticException, SemanticException {
		Atributos atribExpresionOr = new Atributos();
		Atributos atribExpresionAnd = ExpresionAnd();
		String esAsignable = "false";
		String esNull = "false";

		Atributos atribExpOr = ExpOr(atribExpresionAnd.getAtributo("tipo"));
		atribExpresionOr.addAtributo("paramVarID",atribExpresionAnd.getAtributo("paramVarID"));
		
		String esAsignExpOr = atribExpOr.getAtributo("esAsignable");
		String esAsignexpAnd = atribExpresionAnd.getAtributo("esAsignable");
		if(esAsignexpAnd.equals("true") && esAsignExpOr.equals("true"))
			esAsignable = "true";
		
		String esNullExpOr = atribExpOr.getAtributo("esNull");
		String esNullexpAnd = atribExpresionAnd.getAtributo("esNull");
		if(esNullexpAnd.equals("true") && esNullExpOr.equals("true"))
			esNull = "true";
		
		atribExpresionOr.addAtributo("tipo", atribExpOr.getAtributo("tipo"));
		atribExpresionOr.addAtributo("esAsignable", esAsignable);
		atribExpresionOr.addAtributo("esNull", esNull);
		
		return atribExpresionOr;
	}

	Atributos ExpOr(String TH) throws SyntacticException, SemanticException {
		Atributos atribExpOR = new Atributos();
		String esAsignable = "false";
		String esNull = "false";
		if (lookAhead.get_nombre().equals(TK_AND)) {
			Match(TK_AND);
			Atributos atribExpresionAnd = ExpresionAnd();
			atribExpOR.addAtributo("paramVarID",atribExpresionAnd.getAtributo("paramVarID"));
			 gen.genLn("", "AND", "", "");
			//
			if ((!atribExpresionAnd.getAtributo("tipo").equals(TH))
					&& (atribExpresionAnd.getAtributo("tipo").equals("boolean")))
				throw new SemanticException(
						"operacion solo aplicable a boolean",
						lookAhead.get_numLinea());
			Atributos atribExpOr2 = ExpOr(atribExpresionAnd.getAtributo("tipo"));
			atribExpOR.addAtributo("tipo", atribExpOr2.getAtributo("tipo"));

		} else {
			esNull = "true";
			esAsignable = "true";
			atribExpOR.addAtributo("tipo", TH);
			
		}
		atribExpOR.addAtributo("esAsignable",esAsignable);
		atribExpOR.addAtributo("esNull",esNull);
		return atribExpOR;
	}

	Atributos ExpresionAnd() throws SyntacticException, SemanticException {
		String esAsignable = "false";
		String esNull = "false";
		Atributos atribExpresionAnd = new Atributos();
		Atributos atribExpresionComp = ExpresionComp();
		Atributos atribExpAnd = ExpAnd(atribExpresionComp.getAtributo("tipo"));
		atribExpresionAnd.addAtributo("paramVarID",atribExpresionComp.getAtributo("paramVarID"));
		
		String esAsignExpComp = atribExpresionComp.getAtributo("esAsignable");
		String esAsignExpAnd = atribExpAnd.getAtributo("esAsignable");
		if(esAsignExpAnd.equals("true") && esAsignExpComp.equals("true"))
			esAsignable = "true";
		
		String esNullExpComp = atribExpresionComp.getAtributo("esNull");
		String esNullExpAnd = atribExpAnd.getAtributo("esNull");
		if(esNullExpAnd.equals("true") && esNullExpComp.equals("true"))
			esNull = "true";
		
		atribExpresionAnd.addAtributo("tipo", atribExpAnd.getAtributo("tipo"));
		atribExpresionAnd.addAtributo("esAsignable", esAsignable);
		atribExpresionAnd.addAtributo("esNull", esNull);
		return atribExpresionAnd;

	}

	Atributos ExpAnd(String TH) throws SyntacticException, SemanticException {
		String esAsignable = "false";
		String esNull = "false";
		Atributos atribExpAnd = new Atributos();
		Atributos atribExpAnd2;
		Atributos atribExpresionComp;
		String tipo = TH;
		if (lookAhead.get_nombre().equals(TK_DIST)) {
			Match(TK_DIST);
			atribExpresionComp = ExpresionComp();
			 gen.genLn("", "NE", "", "");
			atribExpAnd2 = ExpAnd(atribExpresionComp.getAtributo("tipo"));
			// ******Chequeo semantico*****
			if (!(TS.esConformante(TH, atribExpresionComp.getAtributo("tipo"),atribExpresionComp.getAtributo("esNull")))
					&& atribExpAnd2.getAtributo("esLambda").equals("true"))
				throw new SemanticException("semantico",lookAhead.get_numLinea());
			tipo="boolean";

			// ****fin chequeo semantico*****
		} else if (lookAhead.get_nombre().equals(TK_DIGUAL)) {
			Match(TK_DIGUAL);
			atribExpresionComp = ExpresionComp();gen.genLn("", "EQ", "", "");
			atribExpAnd2 = ExpAnd(atribExpresionComp.getAtributo("tipo"));
			// ******Chequeo semantico*****
			if (!(TS.esConformante(TH, atribExpresionComp.getAtributo("tipo"),atribExpresionComp.getAtributo("esNull")))
					&& atribExpAnd2.getAtributo("esLambda").equals("true"))
				throw new SemanticException("semantico",lookAhead.get_numLinea());
			tipo="boolean";
			// ****fin chequeo semantico*****
		} else {
			esAsignable = "true";
			esNull = "true";
			atribExpAnd.addAtributo("esLambda", "true");
			
		}
		atribExpAnd.addAtributo("esAsignable",esAsignable);
		atribExpAnd.addAtributo("tipo",tipo);
		atribExpAnd.addAtributo("esNull",esNull);
		return atribExpAnd;
	}

	Atributos ExpresionComp() throws SyntacticException, SemanticException {
		String esAsignable = "false";
		String esNull = "false";
		Atributos atribExpresionComp = new Atributos();
		Atributos atribExpresionSR = ExpresionSR();		
		Atributos atribExpComp = ExpComp(atribExpresionSR.getAtributo("tipo"));
		atribExpresionComp.addAtributo("paramVarID",atribExpresionSR.getAtributo("paramVarID"));
		
		String esAsignExpSR = atribExpresionSR.getAtributo("esAsignable");
		String esAsignExpComp = atribExpComp.getAtributo("esAsignable");
		if(esAsignExpComp.equals("true") && esAsignExpSR.equals("true"))
			esAsignable = "true";
		
		String esNullExpSR = atribExpresionSR.getAtributo("esNull");
		String esNullExpComp = atribExpComp.getAtributo("esNull");
		if(esNullExpComp.equals("true") && esNullExpSR.equals("true"))
			esNull = "true";
		
		atribExpresionComp.addAtributo("tipo", atribExpComp.getAtributo("tipo"));
		atribExpresionComp.addAtributo("esAsignable", esAsignable);
		atribExpresionComp.addAtributo("esNull", esNull);
		return atribExpresionComp;

	}

	Atributos ExpComp(String TH) throws SyntacticException, SemanticException {
		Atributos atribExpComp = new Atributos();
		Atributos atribExpresionSR;
		String tipo = "boolean";
		String esAsignable = "false";
		String esNull = "false";
		if (lookAhead.get_nombre().equals(TK_MAYIG)) {
			Match(TK_MAYIG);
			atribExpresionSR = ExpresionSR();
			atribExpComp.addAtributo("paramVarID",atribExpresionSR.getAtributo("paramVarID"));
			 gen.genLn("", "GE", "", "");
			if (!(atribExpresionSR.getAtributo("tipo").equals(TH))
					&& (atribExpresionSR.getAtributo("tipo").equals("int")))
				throw new SemanticException("semantico: tipos no compatibles",lookAhead.get_numLinea());
		} else if (lookAhead.get_nombre().equals(TK_MENIG)) {
			Match(TK_MENIG);
			;
			atribExpresionSR = ExpresionSR();
			atribExpComp.addAtributo("paramVarID",atribExpresionSR.getAtributo("paramVarID"));
			 gen.genLn("", "LE", "", "");
			if (!(atribExpresionSR.getAtributo("tipo").equals(TH))
					&& (atribExpresionSR.getAtributo("tipo").equals("int")))
				throw new SemanticException("semantico: tipos no compatibles",
						lookAhead.get_numLinea());			
		} else if (lookAhead.get_nombre().equals(TK_MAY)) {
			Match(TK_MAY);
			atribExpresionSR = ExpresionSR();
			atribExpComp.addAtributo("paramVarID",atribExpresionSR.getAtributo("paramVarID"));
			 gen.genLn("", "GT", "", "");
			if (!(atribExpresionSR.getAtributo("tipo").equals(TH))
					&& (atribExpresionSR.getAtributo("tipo").equals("int")))
				throw new SemanticException("semantico: tipos no compatibles",
						lookAhead.get_numLinea());			
		} else if (lookAhead.get_nombre().equals(TK_MEN)) {
			Match(TK_MEN);
			atribExpresionSR = ExpresionSR();
			atribExpComp.addAtributo("paramVarID",atribExpresionSR.getAtributo("paramVarID"));
				 gen.genLn("", "LT", "", "");
			if (!(atribExpresionSR.getAtributo("tipo").equals(TH))
					&& (atribExpresionSR.getAtributo("tipo").equals("int")))
				throw new SemanticException("semantico: tipos no compatibles",
						lookAhead.get_numLinea());		
		} else {
			esAsignable = "true";
			esNull = "true";
			tipo = TH;
		}
		atribExpComp.addAtributo("esAsignable", esAsignable);
		atribExpComp.addAtributo("tipo", tipo);
		atribExpComp.addAtributo("esNull", esNull);
		return atribExpComp;
	}

	Atributos ExpresionSR() throws SyntacticException, SemanticException {
		String esAsignable = "false";
		String esNull = "false";
		Atributos atribExpresionSR = new Atributos();
		Atributos atribTermino = Termino();
		Atributos atribExpSR = ExpSR(atribTermino.getAtributo("tipo"));
		atribExpresionSR.addAtributo("tipo", atribExpSR.getAtributo("tipo"));
		String esAsignExpSR = atribExpSR.getAtributo("esAsignable");
		String esAsignTerm = atribTermino.getAtributo("esAsignable");
		String esNullExpSR = atribExpSR.getAtributo("esNull");
		String esNullTerm = atribTermino.getAtributo("esNull");
		if(esAsignExpSR.equals("true") && esAsignTerm.equals("true"))
			esAsignable = "true";
		if(esNullExpSR.equals("true") && esNullTerm.equals("true"))
			esNull = "true";
		atribExpresionSR.addAtributo("esAsignable",esAsignable);
		atribExpresionSR.addAtributo("esNull",esNull);
		atribExpresionSR.addAtributo("paramVarID",atribTermino.getAtributo("paramVarID"));
		return atribExpresionSR;

	}

	Atributos ExpSR(String TH) throws SyntacticException, SemanticException {
		Atributos atribExpSR = new Atributos();
		Atributos atribTermino;
		Atributos atribExpSR2;
		String esAsignable = "false";
		String esNull = "false";
		if (lookAhead.get_nombre().equals(TK_MAS)) {
			Match(TK_MAS);
			atribTermino = Termino();
			atribExpSR.addAtributo("paramVarID",atribTermino.getAtributo("paramVarID"));
			gen.genLn("", "ADD", "", "");
			if (!(atribTermino.getAtributo("tipo").equals(TH))
					&& (atribTermino.getAtributo("tipo").equals("int")))
				throw new SemanticException("semantico: tipos no compatibles",
						lookAhead.get_numLinea());
			atribExpSR2 = ExpSR(atribTermino.getAtributo("tipo"));
			atribExpSR.addAtributo("tipo", atribExpSR2.getAtributo("tipo"));

		} else if (lookAhead.get_nombre().equals(TK_MENOS)) {
			Match(TK_MENOS);
			atribTermino = Termino();
			atribExpSR.addAtributo("paramVarID",atribTermino.getAtributo("paramVarID"));
			//@@@@@@@@
			 gen.genLn("", "SUB", "", "");
			//@@@@@@@
			if (!(atribTermino.getAtributo("tipo").equals(TH))
					&& (atribTermino.getAtributo("tipo").equals("int")))
				throw new SemanticException("semantico: tipos no compatibles",
						lookAhead.get_numLinea());
			atribExpSR2 = ExpSR(atribTermino.getAtributo("tipo"));
			atribExpSR.addAtributo("tipo", atribExpSR2.getAtributo("tipo"));
		} else {
			atribExpSR.addAtributo("tipo", TH);
			esAsignable = "true";
			esNull = "true";
		}
		atribExpSR.addAtributo("esAsignable",esAsignable);
		atribExpSR.addAtributo("esNull",esNull);
		return atribExpSR;
	}

	Atributos Termino() throws SyntacticException, SemanticException {
		Atributos atribTermino = new Atributos();
		Atributos atribFactor = Factor();
		Atributos atribTerm = Term(atribFactor.getAtributo("tipo"));
		atribTermino.addAtributo("tipo", atribTerm.getAtributo("tipo"));
//		atribTermino.addAtributo("paramVarID",atribTerm.getAtributo("paramVarID"));
		if(atribTerm.getAtributo("esAsignable").equals("true") && atribFactor.getAtributo("esAsignable").equals("true"))
			atribTermino.addAtributo("esAsignable","true");		
		else
			atribTermino.addAtributo("esAsignable","false");
		if(atribTerm.getAtributo("esNull").equals("true") && atribFactor.getAtributo("esNull").equals("true"))
			atribTermino.addAtributo("esNull","true");		
		else
			atribTermino.addAtributo("esNull","false");
		atribTermino.addAtributo("paramVarID",atribFactor.getAtributo("paramVarID"));
		return atribTermino;

	}

	Atributos Term(String TH) throws SyntacticException, SemanticException {
		Atributos atribTerm = new Atributos();
		String esAsign = "false";
		String esNull = "false";
		if (lookAhead.get_nombre().equals(TK_POR)) {
			Match(lookAhead.get_nombre());
			Atributos atribFactor = Factor();
			atribTerm.addAtributo("paramVarID",atribFactor.getAtributo("paramVarID"));
			 gen.genLn("", "MUL", "", "");
			if (!((atribFactor.getAtributo("tipo").equals(TH))
					&& (atribFactor.getAtributo("tipo").equals("int"))))
				throw new SemanticException("semantico: tipos no compatibles",
						lookAhead.get_numLinea());
			Atributos atribTerm2 = Term(TH);
			atribTerm.addAtributo("paramVarID",atribFactor.getAtributo("paramVarID"));
			atribTerm.addAtributo("tipo", atribTerm2.getAtributo("tipo"));
		} else if (lookAhead.get_nombre().equals(TK_MOD)) {
			Match(lookAhead.get_nombre());
			Atributos atribFactor = Factor();
			atribTerm.addAtributo("paramVarID",atribFactor.getAtributo("paramVarID"));
			gen.genLn("", "MOD", "", "");
			if (!((atribFactor.getAtributo("tipo").equals(TH))
					&& (atribFactor.getAtributo("tipo").equals("int"))))
				throw new SemanticException("semantico: tipos no compatibles",
						lookAhead.get_numLinea());
			Atributos atribTerm2 = Term(TH);
			atribTerm.addAtributo("tipo", atribTerm2.getAtributo("tipo"));
			atribTerm.addAtributo("paramVarID",atribFactor.getAtributo("paramVarID"));
		} else if (lookAhead.get_nombre().equals(TK_DIV)) {
			Match(lookAhead.get_nombre());
			Atributos atribFactor = Factor();
			atribTerm.addAtributo("paramVarID",atribFactor.getAtributo("paramVarID"));
			 gen.genLn("", "DIV", "", "");
			if (!((atribFactor.getAtributo("tipo").equals(TH))
					&& (atribFactor.getAtributo("tipo").equals("int"))))
				throw new SemanticException("semantico: tipos no compatibles",
						lookAhead.get_numLinea());
			Atributos atribTerm2 = Term(TH);
			atribTerm.addAtributo("tipo", atribTerm2.getAtributo("tipo"));
			atribTerm.addAtributo("paramVarID",atribFactor.getAtributo("paramVarID"));
		} else {
			esAsign = "true"; //es lambda aca?
			atribTerm.addAtributo("tipo", TH);
			esNull = "true";
		}
		atribTerm.addAtributo("esAsignable",esAsign);
		atribTerm.addAtributo("esNull",esNull);		
		return atribTerm;
	}

	Atributos Factor() throws SyntacticException, SemanticException {
		Atributos atribFactor = new Atributos();
		String esAsign = "false";
		String esNull = "false";
		if (lookAhead.get_nombre().equals(TK_NOT)) {
			Match(TK_NOT);
			Atributos atribFactor2 = Factor();
			if (!atribFactor2.getAtributo("tipo").equals("boolean"))
				throw new SemanticException(
						"operacion solo valido para booleanos",
						lookAhead.get_numLinea());
			atribFactor.addAtributo("tipo", atribFactor2.getAtributo("tipo"));
		} else if (lookAhead.get_nombre().equals(TK_MAS)) {
			Match(TK_MAS);
			Atributos atribFactor2 = Factor();
			if (!atribFactor2.getAtributo("tipo").equals("int"))
				throw new SemanticException(
						"operacion solo valido para enteros",
						lookAhead.get_numLinea());
			atribFactor.addAtributo("tipo", atribFactor2.getAtributo("tipo"));
		} else if (lookAhead.get_nombre().equals(TK_MENOS)) {
			Match(TK_MENOS);
			Atributos atribFactor2 = Factor();
			if (!atribFactor2.getAtributo("tipo").equals("int"))
				throw new SemanticException(
						"operacion solo valido para enteros",
						lookAhead.get_numLinea());
			atribFactor.addAtributo("tipo", atribFactor2.getAtributo("tipo"));
		} else {
			Atributos atribPrimary = Primary();
			atribFactor.addAtributo("tipo", atribPrimary.getAtributo("tipo"));
			esNull = "true";
			esAsign = atribPrimary.getAtributo("esAsignable");
			atribFactor.addAtributo("paramVarID",atribPrimary.getAtributo("paramVarID"));
		}
		atribFactor.addAtributo("esAsignable",esAsign);
		atribFactor.addAtributo("esNull",esNull);
		
		return atribFactor;
	}

	Atributos Primary() throws SyntacticException, SemanticException {
		Atributos atribPrimary = new Atributos();
		atribPrimary.addAtributo("paramVarID","");
		Atributos atribNewPrimary;
		Atributos atribliteral;
		Atributos atribNP;
		Atributos atribINP;
		String nombMet = "";
		String nomClase = "";
		String esNull = "false";
		String tipo = "";
		String esAsignable = "false";
		if (compString(new String[] { TK_NULL, TK_TRUE, TK_FALSE, TK_NUMERO,
				TK_CHARLITERAL, TK_CAD }, lookAhead.get_nombre())) {
			atribliteral = Literal();
			atribNewPrimary = NewPrimary(null,atribliteral.getAtributo("tipo"));
			if (atribNewPrimary.getAtributo("esLambda").equals("false"))
				throw new SemanticException("no es valido",	lookAhead.get_numLinea());
			tipo = atribliteral.getAtributo("tipo");
			esNull = atribliteral.getAtributo("esNull");
			

		} else if (lookAhead.get_nombre().equals(TK_PARENTESISABRE)) {
			Match(TK_PARENTESISABRE);
			Atributos atribExpresion = Expression();

			if (lookAhead.get_nombre().equals(TK_PARENTESISCIERRA)) {
				Match(TK_PARENTESISCIERRA);
			} else {
				throw new SyntacticException(" parantesis '('  ",
						lookAhead.get_lexema(), lookAhead.get_numLinea());
			}
			atribNewPrimary = NewPrimary(null,atribExpresion.getAtributo("tipo"));
			tipo = atribNewPrimary.getAtributo("tipo");			

		} else if (lookAhead.get_nombre().equals(TK_NEW)) {
			Match(TK_NEW);
			if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
				nomClase = lookAhead.get_lexema();
				EntradaClase clase = TS.getClase(lookAhead.get_lexema());
				if (clase == null)
					throw new SemanticException("no existe la clase",
							lookAhead.get_numLinea());
				Match(TK_IDENTIFIER);
			} else {
				throw new SyntacticException(" identificador ",
						lookAhead.get_lexema(), lookAhead.get_numLinea());
			}
	         //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
		
			gen.genLn("", "RMEM", "1","; espacio para el this");
			gen.genLnConOffset("", "PUSH",gen.labelMaxOffset(nomClase),"; push cantidad de variables del objeto a crear");
			gen.genLn("", "PUSH", "simple_malloc","");
			gen.genLn("", "CALL", "","; llamado a malloc, me devuelve el this");
			gen.genLn("", "DUP", "","");
			gen.genLn("", "PUSH",gen.labelVT(nomClase),"");
			gen.genLn("", "STOREREF", "0","; en tope quedo this");
			gen.genLn("", "DUP ", "","; duplico dir de this ");
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			ActualArgs(nomClase, nomClase);
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			gen.genLn("", "PUSH",gen.labelConstructor(nomClase), "; push del label del constructor");
			gen.genLn("", "CALL", "", "");
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			atribNewPrimary = NewPrimary(null,nomClase);
			tipo = atribNewPrimary.getAtributo("tipo");			
		} else if (lookAhead.get_nombre().equals(TK_SUPER)) {
			EntradaMetodo metodo;
			Match(TK_SUPER);
			if (lookAhead.get_nombre().equals(TK_PUNTO)) {
				Match(TK_PUNTO);
				if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
					nombMet = lookAhead.get_lexema();
					metodo = TS.getMetodoHeredado(nombMet);
					if (metodo == null) {
						throw new SemanticException("no existe el metodo",
								lookAhead.get_numLinea());
					}

					Match(TK_IDENTIFIER);
				} else {
					throw new SyntacticException("un identificador",
							lookAhead.get_lexema(), lookAhead.get_numLinea());
				}
				nomClase = TS.getClaseActual().getPadre().getNombre();
				//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
				//LLAMADA A METODO
				gen.genLn("", "LOAD", "3", "; carga el this del RA del m�todo mA (llamador)");
				gen.genLn("", "RMEM", "1", "; Deja lugar para el return del m�todo ");
				gen.genLn("", "SWAP	", "","; ");
				//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
				ActualArgs(nomClase, nombMet);
				//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			//	gen.genLn("", "DUP", "","; ; duplico la referencia a �this� para hacer el loadref del VT");
				gen.genLn("", "PUSH", "vt_"+nomClase,"; ; duplico la referencia a �this� para hacer el loadref del VT");
				//gen.genLn("","LOADREF", "0","; cargo la referencia a la VT en la pila");
				gen.genLn("", "LOADREF",TS.getMetodoHeredado(nombMet).getOffset()+"", " ;Carga la direcci�n del metodo");
				gen.genLn("", "CALL","","; llamo al m�todo referenciado en el tope de la pila");
				//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
				
				atribNewPrimary = NewPrimary(null,metodo.getTipo());
				tipo = atribNewPrimary.getAtributo("tipo");				
			} else {
				throw new SyntacticException("\'.\'", lookAhead.get_lexema(),
						lookAhead.get_numLinea());
			}
		} else if (lookAhead.get_nombre().equals(TK_THIS)) {
			Match(TK_THIS);
			atribNP = NP(TS.getClaseActual().getNombre());
			tipo = atribNP.getAtributo("tipo");
			esAsignable = atribNP.getAtributo("esAsignable");
		} else if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {			
			atribPrimary.addAtributo("paramVarID",lookAhead.get_lexema());
			String aux = lookAhead.get_lexema();
			Match(TK_IDENTIFIER);
			tipo = TS.getClaseActual().getNombre();			
			atribINP = INP(aux,tipo);
			esAsignable = atribINP.getAtributo("esAsignable");
			tipo = atribINP.getAtributo("tipo");
			

		} else {
			throw new SyntacticException("una expresion valida",
					lookAhead.get_lexema(), lookAhead.get_numLinea());
		}
		atribPrimary.addAtributo("esNull",esNull);
		atribPrimary.addAtributo("tipo", tipo);
		atribPrimary.addAtributo("esAsignable", esAsignable);
		return atribPrimary;
	}

	Atributos NP(String clase) throws SyntacticException, SemanticException {
		Atributos atribNP = new Atributos();
		Atributos atribNP2;
		String identifier = "";
		if (lookAhead.get_nombre().equals(TK_PUNTO)) {
			Match(TK_PUNTO);
			if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
				identifier = lookAhead.get_lexema();
			//	if (TS.getClase(clase).getMetodoGral(identifier) == null)
				//	throw new SemanticException("no existe el metodo",lookAhead.get_numLinea());

				Match(TK_IDENTIFIER);
			} else {
				throw new SyntacticException("un identificador",
						lookAhead.get_lexema(), lookAhead.get_numLinea());
			}
			atribNP2 = NP2(clase, identifier);
			atribNP.addAtributo("tipo", atribNP2.getAtributo("tipo"));
			atribNP.addAtributo("esAsignable",
					atribNP2.getAtributo("esAsignable"));
		} else {
			atribNP.addAtributo("tipo", clase);
			atribNP.addAtributo("esAsignable", "false");
		}
		return atribNP;
	}

	Atributos NP2(String clase, String metodo) throws SyntacticException,SemanticException {
		Atributos atribNP2 = new Atributos();
		Atributos atribNewPrimary;
		if (lookAhead.get_nombre().equals(TK_PARENTESISABRE)) {
			EntradaMetodo met = TS.getClase(clase).getMetodo(metodo);
			if(met == null)
				throw new SemanticException("El metodo "+metodo+" no esta declarado", lookAhead.get_numLinea());
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			//LLAMADA A METODO
			gen.genLn("", "LOAD", "3", "; c arga el this del RA del m�todo mA (llamador)");
			gen.genLn("", "RMEM", "1", "; Deja lugar para el return del m�todo ");
			gen.genLn("", "SWAP	", "","; ");
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			ActualArgs(clase, metodo);
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			gen.genLn("", "DUP", "","; ; duplico la referencia a �this� para hacer el loadref del VT");
			gen.genLn("","LOADREF", "0","; cargo la referencia a la VT en la pila");
			gen.genLn("", "LOADREF",TS.getClase(clase).getMetodo(metodo).getOffset()+"", " ;Carga la direcci�n del metodo");
			gen.genLn("", "CALL","","; llamo al m�todo referenciado en el tope de la pila");
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			atribNewPrimary = NewPrimary(metodo,TS.getClase(clase).getMetodo(metodo).getTipo());
			atribNP2.addAtributo("esAsignable", "false");
			atribNP2.addAtributo("tipo", atribNewPrimary.getAtributo("tipo"));

		} else {
			EntradaVariable var = TS.getClase(clase).getVariable(metodo);
			if(var == null)
				throw new SemanticException("La variable "+metodo+" no esta definida", lookAhead.get_numLinea());
			
			
			gen.genLn("", "LOAD",3+"", "; cargamos la referencia al this");
			//gen.genLn("", "DUP","", "; duplicamos la referencia al this");
			gen.genLnConOffset("", "LOADREF",""+gen.labelOffset(TS.getClaseActual().getNombre(), metodo),";guardo la variable "+metodo );
			atribNewPrimary = NewPrimary(metodo,TS.getClase(clase).getVariable(metodo).getTipo());
			atribNP2.addAtributo("tipo", atribNewPrimary.getAtributo("tipo"));
			atribNP2.addAtributo("esAsignable",atribNewPrimary.getAtributo("esAsignable"));
		}
		return atribNP2;
	}

	Atributos INP(String identificador, String TH) throws SyntacticException,SemanticException {
		Atributos atribINP = new Atributos();
		Atributos atribNewPrimary;
		String esAsign = "false";
		String tipo;
		if (lookAhead.get_nombre().equals(TK_PARENTESISABRE)) {			
			// es un metodo de la clase
			EntradaMetodo met = TS.getClase(TH).getMetodoGral(identificador);
			if(met == null)
				throw new SemanticException("El metodo "+identificador+" no esta declarado", lookAhead.get_numLinea());
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			//LLAADA A METODO
			gen.genLn("", "LOAD", "3", "; c arga el this del RA del m�todo mA (llamador)");
			gen.genLn("", "RMEM", "1", "; Deja lugar para el return del m�todo ");
			gen.genLn("", "SWAP	", "","; ");
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			ActualArgs(TS.getClaseActual().getNombre(), identificador);
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			gen.genLn("", "DUP", "","; ; duplico la referencia a �this� para hacer el loadref del VT");
			gen.genLn("", "DUP", "","; ; duplico la referencia a �this� para hacer el chequeo de nulo");
			gen.genLn("", "BF", "nullPointer",";chequea que la referencia no sea nula en tiempo de ejecuci�n");			
			gen.genLn("","LOADREF", "0","; cargo la referencia a la VT en la pila");
			gen.genLn("", "LOADREF",TS.getClase(TH).getMetodoGral(identificador).getOffset()+"", "; ;Carga la direcci�n del metodo");
			gen.genLn("", "CALL","","; llamo al m�todo referenciado en el tope de la pila");
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			atribNewPrimary = NewPrimary(identificador,TS.getClase(TH).getMetodoGral(identificador).getTipo());
			esAsign = "false";
			tipo = atribNewPrimary.getAtributo("tipo");
		}
		else{
			/*EntradaVariable idVar = TS.getMetodoActual().getParam(lookAhead.get_lexema());
			if(idVar != null){ //es parametro
				
				
			}else{ //es una variable de instancia
				
			}*/
			EntradaVariable Var = TS.getMetodoActual().getParam(identificador);
			if(Var != null){ //es un parametro
				gen.genLn("", "LOAD",( Var.getOffset()+3)+"", "; parametro");				
			}
			else{
				Var = TS.getClaseActual().getVariable(identificador);
				if(Var == null)
					throw new SemanticException("Variable no declarada", lookAhead.get_numLinea());
				gen.genLn("","LOAD","3",";cargo la referencia al CIR del metodo (offset 3 del RA)");
				gen.genLnConOffset("", "LOADREF", gen.labelOffset(TS.getClaseActual().getNombre(),identificador), "; variable de instancia");
			}
			atribNewPrimary = NewPrimary(identificador,Var.getTipo());
			tipo = atribNewPrimary.getAtributo("tipo");
			esAsign = atribNewPrimary.getAtributo("esAsignable");
		}
		atribINP.addAtributo("esAsignable",	esAsign);
		atribINP.addAtributo("tipo", tipo);
		return atribINP;
		// no chequea si hay error porque puede derivar en vac�o (si en lugar de
		// un punto, es "lambda" y entra a newprimary por ahi, ya que lambda es
		// primero de newprimary)
	}

	Atributos NewPrimary(String IdH,String TH) throws SyntacticException,
			SemanticException {
		Atributos atribNewPrimary = new Atributos();
		Atributos atribNewPrimary2;
		String id;
		if (lookAhead.get_nombre().equals(TK_PUNTO)) {
			Match(TK_PUNTO);
			if (esTipoPrimitivo(TH))
				throw new SemanticException("operacion invalida sobre un tipo primitivo", lookAhead.get_numLinea());
			if(TS.getClase(TH) == null)
				throw new SemanticException("Tipo invalido", lookAhead.get_numLinea());
			if (lookAhead.get_nombre().equals(TK_IDENTIFIER)) {
				id = lookAhead.get_lexema();
				Match(TK_IDENTIFIER);				
				if (TS.getClase(TH).getMetodoGral(id) == null)
					throw new SemanticException("no existe el metodo",lookAhead.get_numLinea());
			} else {
				throw new SyntacticException("un identificador",
						lookAhead.get_lexema(), lookAhead.get_numLinea());
			}
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			//gen.genLn("", "LOAD", "3", "; c arga el this del RA del m�todo mA (llamador)");
			gen.genLn("", "RMEM", "1", "; Deja lugar para el return del m�todo ");
			gen.genLn("", "SWAP	", "","; ");
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			ActualArgs(TH, id);
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			gen.genLn("", "DUP", "","; ; duplico la referencia a �this� para hacer el loadref del VT");
			gen.genLn("", "DUP", "","; ; duplico la referencia a �this� para hacer el chequeo de nulo");
			gen.genLn("", "BF", "nullPointer",";chequea que la referencia no sea nula en tiempo de ejecuci�n");
			gen.genLn("","LOADREF", "0","; cargo la referencia a la VT en la pila");
			gen.genLn("", "LOADREF",TS.getClase(TH).getMetodoGral(id).getOffset()+"", "; ;Carga la direcci�n del metodo");
			gen.genLn("", "CALL","","; llamo al m�todo referenciado en el tope de la pila");
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			atribNewPrimary2 = NewPrimary(null,TS.getClase(TH).getMetodoGral(id)
					.getTipo());
			atribNewPrimary.addAtributo("tipo",
					atribNewPrimary2.getAtributo("tipo"));
			atribNewPrimary.addAtributo("esAsignable", "false");
		} else {
			atribNewPrimary.addAtributo("esAsignable", "true");
			atribNewPrimary.addAtributo("esLambda", "true");
			atribNewPrimary.addAtributo("tipo", TH);
		}
		return atribNewPrimary;
	}

	Atributos Literal() throws SyntacticException {
		String esNull = "false";
		Atributos atribLiteral = new Atributos();
		if (lookAhead.get_nombre().equals(TK_NULL)) {
			esNull = "true";
			atribLiteral.addAtributo("tipo", "Object");
			gen.genLn("", "PUSH","0","");
			Match(lookAhead.get_nombre());
		} else if (lookAhead.get_nombre().equals(TK_TRUE)) {
			atribLiteral.addAtributo("tipo", "boolean");
			gen.genLn("", "PUSH","1","");
			Match(lookAhead.get_nombre());
		} else if (lookAhead.get_nombre().equals(TK_FALSE)) {
			atribLiteral.addAtributo("tipo", "boolean");
			gen.genLn("", "PUSH","0","");
			Match(lookAhead.get_nombre());
		} else if (lookAhead.get_nombre().equals(TK_NUMERO)) {
			atribLiteral.addAtributo("tipo", "int");
			gen.genLn("", "PUSH",lookAhead.get_lexema() ,"");
			Match(lookAhead.get_nombre());
		} else if (lookAhead.get_nombre().equals(TK_CHARLITERAL)) {
			atribLiteral.addAtributo("tipo", "char");
			gen.genLn("", "PUSH","\'"+lookAhead.get_lexema()+"\'","");
			Match(lookAhead.get_nombre());
		} else if (lookAhead.get_nombre().equals(TK_CAD)) {
			atribLiteral.addAtributo("tipo", "String");
			String cad=lookAhead.get_lexema();
			int l=cad.length()+1;
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			gen.genLn("", "RMEM","1" ,"");
			gen.genLn("", "PUSH", l+"", "");
			gen.genLn("", "PUSH", "simple_malloc", "");
			gen.genLn("", "CALL", "", "");
			int i=0;
				for (char caracter : cad.toCharArray()) {
				 	gen.genLn("", "DUP", "", "");
				 	gen.genLn("", "PUSH",  "\'"+caracter+ "\'", "");
				 	gen.genLn("", "STOREREF",i+"" , "");
				 	i++;
				}
				gen.genLn("", "DUP", "", "");
				gen.genLn("", "PUSH", "0", "");
				gen.genLn("", "STOREREF", i+"", "");
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			Match(lookAhead.get_nombre());
		} else {
			throw new SyntacticException("un valor", lookAhead.get_lexema(),
					lookAhead.get_numLinea());
		}
		atribLiteral.addAtributo("esNull", esNull);
		return atribLiteral;
	}

	Atributos ActualArgs(String tipoMet, String nombMet)
			throws SyntacticException, SemanticException {
		Atributos atribActualArgs = new Atributos();
		if (!Match(TK_PARENTESISABRE)) {
			throw new SyntacticException("\'(\'", lookAhead.get_lexema(),
					lookAhead.get_numLinea());
		}
		//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
		//gen.genLn("", "LOAD", "3", "; c arga el this del RA del m�todo mA (llamador)");
		//@@@@@@@@@@@@@@@@@@@@@@@@@@@@
		ExprListM(tipoMet, nombMet);
		if (!TS.getClase(tipoMet).getMetodoGral(nombMet).colaParamVacia())
			throw new SemanticException("faltan parametros",
					lookAhead.get_numLinea());
		if (!Match(TK_PARENTESISCIERRA)) {
			throw new SyntacticException("\')\'", lookAhead.get_lexema(),
					lookAhead.get_numLinea());
		}
		return atribActualArgs;
	}

	void ExprListM(String tipoMet, String nombMet) throws SyntacticException,
			SemanticException {
		if (compString(new String[] { TK_NOT, TK_MAS, TK_MENOS, TK_NULL,
				TK_TRUE, TK_FALSE, TK_NUMERO, TK_CHARLITERAL, TK_CAD,
				TK_PARENTESISABRE, TK_NEW, TK_SUPER, TK_THIS, TK_IDENTIFIER },
				lookAhead.get_nombre())) {
			ExprList(tipoMet, nombMet);

		} else {
			// lambda
		}

	}

	void ExprList(String tipoMet, String nombMet) throws SyntacticException,
			SemanticException {
		Atributos atribExpesion = Expression();
		String check = TS.chequearParamInvoc(tipoMet, nombMet,atribExpesion.getAtributo("tipo"),atribExpesion.getAtributo("esNull"));
		if(check != null)
			throw new SemanticException("El parametro actual es de tipo "+atribExpesion.getAtributo("tipo")+" y se esperaba "+check, lookAhead.get_numLinea());
		gen.genLn("", "SWAP", "", "");
		ExLt(tipoMet, nombMet);
	}

	void ExLt(String tipoMet, String nombMet) throws SyntacticException,
			SemanticException {
		if (lookAhead.get_nombre().equals(TK_COMA)) {
			Match(TK_COMA);
			ExprList(tipoMet, nombMet);
		} else {
			// LAMBDA!
		}
	}

	Atributos ExpIg(String TH) throws SyntacticException, SemanticException {
		String esAsignable = "false";
		String esNull = "false";
		Atributos atribExpIg = new Atributos();
		if (lookAhead.get_nombre().equals(TK_OR)) {
			Match(TK_OR);
		
			Atributos atribExpresionOr = ExpresionOr();
			gen.genLn("", "OR", "", "");

			if ((atribExpresionOr.getAtributo("tipo").equals(TH))
					&& (atribExpresionOr.getAtributo("tipo").equals("boolean")))
				atribExpIg.addAtributo("TH",
						atribExpresionOr.getAtributo("tipo"));
			else
				throw new SemanticException("incompatibilidad de tipos,operacion solo aplicable a boolean",
						lookAhead.get_numLinea());

			Atributos atribExpAsig2 = ExpIg(atribExpresionOr.getAtributo("tipo"));
			atribExpIg.addAtributo("tipo", atribExpAsig2.getAtributo("tipo"));
		} else {
			esAsignable = "true";
			esNull = "true";
			atribExpIg.addAtributo("tipo", TH);
		}
		
		atribExpIg.addAtributo("esAsignable",esAsignable);
		atribExpIg.addAtributo("esNull",esNull);
		return atribExpIg;

	}

	boolean Match(String TK_nombre) {
		boolean resul = lookAhead.get_nombre().equals(TK_nombre);
		if (resul) {
			try {
				// System.out.println(lookAhead.get_nombre());
				lookAhead = ALex.getToken();
			} catch (IOException e) {

				e.printStackTrace();
			} catch (LexicalException e) {
				System.out.println(e.getMessage());
				System.exit(2);
			}
		}
		return resul;

	}

	private boolean compString(String[] primeros, String TK_nombre) {
		boolean resul = false;
		for (int i = 0; i < primeros.length && !resul; i++) {
			resul = TK_nombre.equals(primeros[i]);
		}
		return resul;
	}

	private boolean esTipoPrimitivo(String t) {
		return (t.equals("int") || t.equals("boolean") || t.equals("char")
				|| t.equals("String") || t.equals("void"));

	}	 
private void generacionInicial(){
	    
		gen.genLn("", ".CODE", "", "");
		gen.genLn("", "PUSH", "simple_heap_init", "");
		gen.genLn("", "CALL", "", "");
		gen.genLn("", "RMEM", "1", ";espacio para el this");
		gen.genLnConOffset("", "PUSH", gen.labelMaxOffset("main"), ";VT + variables");
		gen.genLn("", "PUSH", "simple_malloc", "");
		gen.genLn("", "CALL", "", ";llamado a malloc, me devuelve el this");
		gen.genLn("", "DUP", "", "");
		gen.genLn("", "PUSH", "vt_main", "");
		gen.genLn("", "STOREREF", "0", ";en tope quedo this");
		gen.genLn("", "DUP", "", ";duplico dir de this ");
		gen.genLn("", "PUSH", "ctr_main", "");
		gen.genLn("", "CALL", "", "");
		gen.genLn("", "HALT ", "", "");
		//Generacion de codigo de simple_heap_init
		gen.genLn("simple_heap_init"+":","","",";este es un label");		
		gen.genLn("", "RET", "0", "; Retorna inmediatamente");
		//Generacion de codigo de malloc
		gen.genLn("simple_malloc"+":","","",";este es un label");
		gen.genLn("","LOADFP","",";enlace dinamico");
		gen.genLn("","LOADSP","","");
		gen.genLn("","STOREFP","",";se setea el FP al inicio del metodo llamado");
		gen.genLn("", "LOADHL", "", "; hl");
		gen.genLn("", "DUP", "", "; hl");
		gen.genLn("", "PUSH", "1", "; 1");
		gen.genLn("", "ADD", "", "; hl+1");		
		gen.genLn("", "STORE", "4", "; Guarda el resultado (un puntero a la primer celda de la regi�n de memoria)");
		gen.genLn("", "LOAD", "3", "; Carga la cantidad de celdas a alojar (par�metro que debe ser positivo)");
		gen.genLn("", "ADD", "", "");
		gen.genLn("", "STOREHL", "", "; Mueve el heap limit (hl). Expande el heap");
		gen.genLn("", "STOREFP", "", "");
		gen.genLn("", "RET", "1", "; Retorna eliminando el par�metro");
		
		gen.genLn("", ".DATA", "", "");
		gen.genLn("msj_nullPointer:", "", "", "");
		gen.genLn("", "DW", "\"NullPointerException, se sale del programa\",0", "");
		gen.genLn("", ".CODE", "", "");
		gen.genLn("nullPointer:","","",";msj de error en caso de referencias nulas");		
		gen.genLn("", "PUSH", "msj_nullPointer", "");		
		gen.genLn("", "SPRINT", "", "");
		gen.genLn("", "HALT", "", "");

	}
	private void generacionMetodosSystem(){
		String label_vt_System="";
		// Generacion de codigo de int read()
		gen.genLn("", ".CODE", "", "");
		String aux="";
		TS.getClase("System").getMetodo("read").setLabel(gen.labelMetodo("System", "read"));
		aux=gen.labelMetodo("System", "read");
		label_vt_System=label_vt_System+aux;
		gen.genLn(aux+":","","",";label read");		
		gen.genLn("","LOADFP","",";enlace dinamico");
		gen.genLn("","LOADSP","","");
		gen.genLn("","STOREFP","",";se setea el FP al inicio del metodo llamado");
		gen.genLn("","READ","",";el read del metodo");
		gen.genLn("","STORE","4",";almacena el valor");
		gen.genLn("","STOREFP","",";setea el FP al inicio del metodo llamador");		
		gen.genLn("","RET","1",";devuelve, y desapila el this");
		//Generacion de codigo de void printB(boolean b)
		TS.getClase("System").getMetodo("printB").setLabel(gen.labelMetodo("System", "printB"));
		aux=gen.labelMetodo("System", "printB");
		label_vt_System=label_vt_System+","+aux;
		gen.genLn(aux+":","","","; label printB");		
		gen.genLn("","LOADFP","",";enlace dinamico");
		gen.genLn("","LOADSP","","");
		gen.genLn("","STOREFP","",";se setea el FP al inicio del metodo llamado");
		gen.genLn("","LOAD", "4", ";cargo el parametro");
		gen.genLn("","BPRINT","","; imprime booleano");
		gen.genLn("","STOREFP","",";setea el FP al inicio del metodo llamador");		
		gen.genLn("","RET","2",";devuelve, y desapila el parametro y el this");
		//Generacion de codigo de void printC(char c)
		TS.getClase("System").getMetodo("printC").setLabel(gen.labelMetodo("System", "printC"));
		aux=gen.labelMetodo("System", "printC");
		label_vt_System=label_vt_System+","+aux;
		gen.genLn(aux+":","","","; label printC");		
		gen.genLn("","LOADFP","",";enlace dinamico");
		gen.genLn("","LOADSP","","");
		gen.genLn("","STOREFP","",";se setea el FP al inicio del metodo llamado");
		gen.genLn("","LOAD", "4", ";cargo el parametro");
		gen.genLn("","CPRINT","","; imprime caracter ");
		gen.genLn("","STOREFP","",";setea el FP al inicio del metodo llamador");		
		gen.genLn("","RET","2",";devuelve, y desapila el parametro y el this");
		//Generacion de codigo de void printI(int i)
		TS.getClase("System").getMetodo("printI").setLabel(gen.labelMetodo("System", "printI"));
		aux=gen.labelMetodo("System", "printI");
		label_vt_System=label_vt_System+","+aux;
		gen.genLn(aux+":","","","; label printI");		
		gen.genLn("","LOADFP","",";enlace dinamico");
		gen.genLn("","LOADSP","","");
		gen.genLn("","STOREFP","",";se setea el FP al inicio del metodo llamado");
		gen.genLn("","LOAD", "4", ";cargo el parametro");
		gen.genLn("","IPRINT","","; imprime enteros");
		gen.genLn("","STOREFP","",";setea el FP al inicio del metodo llamador");		
		gen.genLn("","RET","2",";devuelve, y desapila el parametro y el this");
		//Generacion de codigo de void printS(String s)
		TS.getClase("System").getMetodo("printS").setLabel(gen.labelMetodo("System", "printS"));
		aux=gen.labelMetodo("System", "printS");
		label_vt_System=label_vt_System+","+aux;
		gen.genLn(aux+":","","","; label srintS");		
		gen.genLn("","LOADFP","",";enlace dinamico");
		gen.genLn("","LOADSP","","");
		gen.genLn("","STOREFP","",";se setea el FP al inicio del metodo llamado");
		gen.genLn("","LOAD", "4", ";cargo el parametro");
		gen.genLn("","SPRINT","","; imprime String");
		gen.genLn("","STOREFP","",";setea el FP al inicio del metodo llamador");		
		gen.genLn("","RET","2",";devuelve, y desapila el parametro y el this");
		//Generacion de codigo de void println()
		TS.getClase("System").getMetodo("println").setLabel(gen.labelMetodo("System", "println"));
		aux=gen.labelMetodo("System", "println");
		label_vt_System=label_vt_System+","+aux;
		gen.genLn(aux+":","","","; label println");		
		gen.genLn("","LOADFP","",";enlace dinamico");
		gen.genLn("","LOADSP","","");
		gen.genLn("","STOREFP","",";se setea el FP al inicio del metodo llamado");
		gen.genLn("","PRNLN","","; baja linea");
		gen.genLn("","STOREFP","",";setea el FP al inicio del metodo llamador");		
		gen.genLn("","RET","2",";devuelve, y desapila el parametro y el this");
		//Generacion de codigo de void printBln(boolean b)
		TS.getClase("System").getMetodo("printBln").setLabel(gen.labelMetodo("System", "printBln"));
		aux=gen.labelMetodo("System", "printBln");
		label_vt_System=label_vt_System+","+aux;
		gen.genLn(aux+":","","",";label printBLn");		
		gen.genLn("","LOADFP","",";enlace dinamico");
		gen.genLn("","LOADSP","","");
		gen.genLn("","STOREFP","",";se setea el FP al inicio del metodo llamado");
		gen.genLn("","LOAD", "4", ";cargo el parametro");
		gen.genLn("","BPRINT","","; imprime booleano");
		gen.genLn("","PRNLN","",";el read del metodo");
		gen.genLn("","STOREFP","",";setea el FP al inicio del metodo llamador");		
		gen.genLn("","RET","2",";devuelve, y desapila el parametro y el this");
		//Generacion de codigo de void printCln(char c)
		TS.getClase("System").getMetodo("printCln").setLabel(gen.labelMetodo("System", "printCln"));
		aux=gen.labelMetodo("System", "printCln");
		label_vt_System=label_vt_System+","+aux;
		gen.genLn(aux+":","","","; label printCln");		
		gen.genLn("","LOADFP","",";enlace dinamico");
		gen.genLn("","LOADSP","","");
		gen.genLn("","STOREFP","",";se setea el FP al inicio del metodo llamado");
		gen.genLn("","LOAD", "4", ";cargo el parametro");
		gen.genLn("","CPRINT","","; imprime caracter");
		gen.genLn("","PRNLN","",";el read del metodo");
		gen.genLn("","STOREFP","",";setea el FP al inicio del metodo llamador");		
		gen.genLn("","RET","2",";devuelve, y desapila el parametro y el this");
		//Generacion de codigo de void printIln(int i)
		TS.getClase("System").getMetodo("printIln").setLabel(gen.labelMetodo("System", "printIln"));
		aux=gen.labelMetodo("System", "printIln");
		label_vt_System=label_vt_System+","+aux;
		gen.genLn(aux+":","","","; label printIln");		
		gen.genLn("","LOADFP","",";enlace dinamico");
		gen.genLn("","LOADSP","","");
		gen.genLn("","STOREFP","",";se setea el FP al inicio del metodo llamado");
		gen.genLn("","LOAD", "4", ";cargo el parametro");
		gen.genLn("","IPRINT","","; imprime enteros");
		gen.genLn("","PRNLN","",";el read del metodo");
		gen.genLn("","STOREFP","",";setea el FP al inicio del metodo llamador");		
		gen.genLn("","RET","2",";devuelve, y desapila el parametro y el this");
		//Generacion de codigo de void printSln(String s)
		TS.getClase("System").getMetodo("printSln").setLabel(gen.labelMetodo("System", "printSln"));
		aux=gen.labelMetodo("System", "printSln");
		label_vt_System=label_vt_System+","+aux;
		gen.genLn(aux+":","","","; label printSln");		
		gen.genLn("","LOADFP","",";enlace dinamico");
		gen.genLn("","LOADSP","","");
		gen.genLn("","STOREFP","",";se setea el FP al inicio del metodo llamado");
		gen.genLn("","LOAD", "4", ";cargo el parametro");
		gen.genLn("","SPRINT","","; imprime String");
		gen.genLn("","PRNLN","",";el read del metodo");
		gen.genLn("","STOREFP","",";setea el FP al inicio del metodo llamador");		
		gen.genLn("","RET","2",";devuelve, y desapila el parametro y el this");
		// generacion VT_System
		gen.genLn("", ".DATA", "", "");
	   	 gen.genLn(gen.labelVT("System")+":", "", "", "");
	   	 gen.genLn("", "DW", label_vt_System, "; vt clase "+"System");
	   	 gen.genLn("", ".CODE", "", "");
		//gen.generarArchivo(TS);
		gen.genLn("ctr_System"+":", "", "", "");
		gen.genLn("","LOADFP","",";enlace dinamico");
		gen.genLn("","LOADSP","","");
		gen.genLn("","STOREFP","",";se setea el FP al inicio del metodo llamado");
		gen.genLn("", "STOREFP", "", "");
		gen.genLn("", "RET", "1","");
		
	}
	public void deleteFile(){
		gen.deleteFile();
	}
	public static void main(String[] args) {
		if (args.length == 0) {
			System.out.println("Error: Falta el archivo fuente.");
			System.out
					.println("SINTAXIS: java -jar NOMBRE_PROGRAMA <SOURCEFILE>");
			System.exit(1);
		}
		String destFile="";
		String srcFile = args[0];
		if(args.length == 2)
			destFile = args[1];

		AnalizadorSemantico sem = new AnalizadorSemantico(srcFile,destFile);
		try {
			sem.Start();
			sem.gen.generarArchivo(sem.TS);
			sem.gen.close();
			System.out.println("Analisis semantico exitoso!");
		} catch (SyntacticException e) {
			sem.deleteFile();
			System.out.println(e.getMessage());
		} catch (SemanticException e) {
			sem.deleteFile();
			System.out.println(e.getMessage());
		}
	}

}